|
Subject: A Lispy Forth for Smalltalk Newsgroups: gmane.comp.lang.smalltalk.squeak.general Date: 2004-02-15 01:52:44 GMT (5 years, 19 weeks, 6 days, 22 hours and 36 minutes ago) I've just put up a package called "Sorrow" on SqueakMap, which is an extremely simple compiler for a language inspired by the "functional Forth" Joy (http://www.latrobe.edu.au/philosophy/phimvt/joy/j01tut.html). The compiler takes Squeak arrays as input, and in fact the easiest way to invoke it is to send #value: to an array literal, which will immediately compile and evaluate a new method. It implements a postfix stack language, so there are no variable references or scopes. Any non-symbol objects in the array get pushed onto the stack; a symbol either pushes a global variable onto the stack (if it starts with an uppercase letter) or causes a message send. The message send will pop the appropiate number of arguments off of the stack for the arity of the selector, and dispatch on the last of these (the lowest on the stack). Each method invocation has its own stack, which starts with its receiver and arguments. The top of the stack once the method has finished executing is returned at the end, ie, placed on top of the sender's stack (I'm open to suggestion on the details of this, though). It may be clear that this maps pretty directly to Squeak bytecode, which is why the compiler is so trivial (around 30 lines, but I was being verbose). Block like behavior can be gotten by simply constructing and passing around arrays. Here's a simple example which evaluates to 6 when sent #value - #((1 2 3) 0 (+) inject:into:) You can also use #addSelector:withArray: to install the compiled version of an array in a class, eg, Integer addSelector: #plusOne withArray: #(1 +). 41 onePlus. "42" The methods #swap: and #dup are useful for stack manipulation, eg, Integer addSelector: #double withArray: #(dup +). 21 double. "42" Integer addSelector: #oneDividedBy withArray: #(1 swap: /). 2 oneDividedBy. "1/2" I just did this for fun, but I can almost imagine using these arrays in the same way that people sometimes define #value: on Symbol: someCollection select: #(isOdd) thenCollect: #(2 *) instead of someCollect select: [:ea | ea isOdd] thenCollect: [:ea | ea * 2]. Avi |
|
|