User loginNavigation |
archivesANN: Bipedal, a new, untyped, stack-based HLLIn the seven years since I first began tinkering on what would eventually become Babel, the Internet has exploded with things called Babel. It is, unfortunately, a very popular name for things related to language. So, I've renamed the syntax layer of the language to Bipedal, while the VM is still called "Babel" or "the Babel-core". I spoke on Babel at StrangeLoop 2013 in St. Louis on the 18th. The video will be available sometime in the next few months. Bipedal Bipedal is a front-end for the Babel programming langage core. Babel is essentially the VM on which Bipedal runs. Bipedal progamming language is a general-purpose, untyped, stack-based high-level language. Despite being stack-based, it is not concatenative. It is not pure, as many operators can have side-effects. The syntax-layer is as transparent as possible, so when you look at Bipedal, you're looking at a nearly 1:1 translation to Babel bytecode. Blitz Syntax Overview
There is more to the syntax, but this is enough to introduce some of the key concepts of the language. You can check out more examples at RosettaCode. Bipedal as High-Level Language There are two strikes against Bipedal's use as a HLL: 1) it is stack-based and some people are of the view that stack-based languages are only suited to intermediate-languages, 2) it is untyped. I have attempted to address each of these problems in my design of Bipedal/Babel. Stack-noise reduction Babel actually maintains two stacks: up-stack (ustack) and down-stack (dstack). Let the notation
represent a stack where x has been pushed first, z last, with '|' visually marking the TOS. Now, let us define star_n as a combinator that will print an asterisk n times, where n will be passed on TOS. One way to write the code for this is as follows:
The order of operands for the times operator is "{ code } N times", where N is some number. Since n is being passed on TOS, this creates stack-noise where we must swap the code to be executed with the number of times it is to be executed, already on TOS. Another way to solve this in Babel is to use the up (->) and down (<-) operators:
This has an equivalent effect. A view of the stack images:
In this case, it is not clear that up/down are an improvement over swap - in fact, we have used an additional operation to accomplish the same task. However, the up and down operators allow the stack to be "taken apart" and processed piece-by-piece, for any number of "arguments" passed to a particular operator. To illustrate this, consider the following function in the notation of C:
The arguments are pushed on the stack and then foo is called. If it is possible to perform all processing on a, then b, and then c, then we can apply the following schema using the up/down operators to process foo in a similar way in Babel:
Of course, this pattern will not solve all stack-noise problems, as it can be the case that values on the stack need to be accessed in some arbitrary order with repetitions, such as: a c b c b a c b. The up/down operators are unlikely to reduce stack noise over against the more traditional stack-rotations in this case. So, Babel permits the use of a 'let' construct to allocate local variables:
This construct should not be confused with the let form in Lisp because it does not perform any kind of "binding" - a, b and c in this case are just pointers and the let operator merely saves/restores the pointers (using the rstack). Another tool for tackling stack noise is the nest operator. Nest allows the construction of a stack-discipline using the following rules:
Invoking bar will cause 'b' to be printed to STDOUT and the following will be left on the stack:
Nest allows a nested-section to monopolize the stack. This is useful if you want to generate a bunch of results on the stack and then collect them together into a list (you can use the collect pseudo-operator for this). Using nest in combination with let will give something roughly analogous to an ordinary function-call stack discipline:
Bipedal has a pseudo-operator called args to perform this:
The args pseudo-operator also assigns the elements of the list on TOS (assumed) to a, b and c. Typing Babel does not have any built-in type system, beyond some rudiments to differentiate between pointers and non-pointers. To me, "type" means one of two, completely different concepts: a) The format of data. ASCII is a type specification, XML is a type specification, JPEG image format is a type specification. When you say, "this is type string", it is difficult to say what exactly you mean without talking about the format in which the string data is kept. b) Data-flow connectors, i.e. "you can't put a square peg in a round hole", or "you can't put an int in a char" (usually). Of course, typing systems can convey much more information, but it is my contention that there is no reason why this information must be conveyed through types - for example, the "is-a" and "has-a" relationships. What Babel implements instead of types is a tag - a tag is a hash (typically, from hashing a string) that can be attached to an otherwise untyped data-structure. Of course, tagged things can be composed, so you can have "types all the way down", if you need it. That is, you could track the fact that a string is a string, a number is a number (and its size) and so on. What you don't get (automatically) in Babel is any kind of inference. However, you can implement your combinators in such a way that typing is always tracked through tags. Support for prevalent data forms, I/O Babel has built-in support for operating on UTF-8 encoded strings, numerics, arrays, lists, hash-tables, binary and n-ary trees. Bipedal files are UTF-8 formatted. File and console I/O are supported. Unique or Notable Features The Babel Virtual Machine is ultra-lightweight, making launching of nested virtual machines very cheap. In Babel, the VM is intended to be the natural unit of abstraction. There is no OO support built-in. The advantages of VM abstraction over OO include that the VM can be interrupted, hibernated, forked, and has configurable resource limits (such as memory-allocation, time, file-access privileges, etc.) Other unique or notable features of Babel include:
But We Already Have Factor My answer to this is that, while Babel is a "practical" stack-based language, it's just a completely different flavor of programming language. It's difficult to meaningfully compare very complex things like programming languages, but perhaps it could be put most succinctly this way: Babel is the Perl5 to Factor's Python. Minus Perl's labyrinthine syntax, of course. Another way of comparing the difference is that the Babel binary is right around 100K as of this writing; it may grow as large as 200K by the time Babel is at revision 1.0, but this will mostly be the result of linking in some support for encryption and compression operators. The Babel-core is essentially finished. Babel takes a more minimalist "swiss-army-knife" approach versus the more "kitchen-sink" approach of Factor, which has a 425K core plus an incredible 66M image file of Factor library code. Conclusion Your feedback is welcome. Babel isn't quite ready for prime-time, but it's getting closer every day. If you have a Windows box with Cygwin and ActivePerl, you can just clone Babel from github, run make.pl and you're ready to roll. You don't need a compiler as the repo has a copy of tcc and will compile from that. If you want to try Babel, please do not hesitate to contact me and I'll help you with any questions you may have. By claytonkb at 2013-09-26 08:08 | LtU Forum | login or register to post comments | other blogs | 12717 reads
|
Browse archivesActive forum topics |
Recent comments
22 weeks 3 days ago
22 weeks 4 days ago
22 weeks 4 days ago
44 weeks 5 days ago
49 weeks 5 hours ago
50 weeks 4 days ago
50 weeks 4 days ago
1 year 1 week ago
1 year 5 weeks ago
1 year 5 weeks ago