To run the code: st> PackageLoader fileInPackages: #('Compiler' 'SUnit')! st> ((Smalltalk addSubspace: #NoCandy) addSubspace: #Presrc) addSubspace: #Tests! st> FileStream fileIn: 'Presource.st'; fileIn: 'Testsuite.st'! Testsuite.st's commentary shows how I usually run the testsuite. This is an excerpt from the Backstage manual that briefly explains the current usage of Presource. Future features are planned to minimize the cases where a macro writer might need to refer to RBParseNode's methods directly; in particular, see the PatternMacro usage in Testsuite.st. 2 Changing the Smalltalk language ********************************* ...These modifications originated with a Smalltalk story called "Presource". Presource allows Smalltalk language modifications to be done in an organized, piece-by-piece way, on a class-by-class basis. The only modifications included in Backstage are based on a system called "message macros". These allow complex Smalltalk expressions to be written as simplified message sends, without incurring a penalty for conversion to the more complex form when Backstage executes the expression. Chances are, if you are using Backstage, you have already encountered these message macros without realizing it; we consider this one of the benefits of relying on message macros. 2.1 How message macros work =========================== Here is an example of a Smalltalk method using a message macro. total "Answer the total price of this cart." | subtotal | subtotal := (self itemCosts fold: #+ sendingBlock) - (self discounts inject: 0 into: #- sendingBlock). ^taxFactor * subtotal This is a very simple use of message macros; `#+ sendingBlock' can be replaced with `[:total :itemCost | total + itemCost]'; a similar case holds for `#- sendingBlock'. This particular message macro, named for its apparent message name `#sendingBlock', allows a message name in `Symbol' form to answer a block that, when given a receiver and the correct number of arguments for the message as arguments to the block, will send the message in question to this receiver with these arguments. As you can see in the sample replacement above, this is much more convenient than writing out the block and choosing names for its arguments every time. Now, let's see what a `sendingBlock' method on `Symbol' might look like: sendingBlock "Answer a block that sends me to its first block argument with the remaining block arguments as message arguments." | argVars formStream | (self notEmpty and: [self first isAlphaNumeric and: [self conform: [:ch | ch isAlphaNumeric or: [$: = ch]]]]) ifFalse: [SystemExceptions.InvalidValue signalOn: self reason: 'not a selector']. argVars := (1 to: (self numArgs + 1)) collect: [:i | 'arg' , i displayString]. formStream := WriteStream on: (String new: 64). formStream nextPut: $[. argVars do: [:arg | formStream nextPut: $:; nextPutAll: arg; space]. formStream nextPut: $|; space; nextPutAll: (argVars at: 1). (argVars copyFrom: 2) with: self keywords do: [:argVar :selectorPart | formStream space; nextPutAll: selectorPart; space; nextPutAll: argVar]. formStream nextPutAll: ' ]'. ^UndefinedObject evaluate: formStream contents This is a very expensive way to get a simple transformation, as done with Presource: expandMessage: selector to: receiver withArguments: arguments | receiverGensym argsGensyms messageNode | receiverGensym := MessageMacro newVariable: 'receiver'. argsGensyms := (1 to: receiver value numArgs) collect: [:num | MessageMacro newVariable: 'arg']. messageNode := STInST.RBMessageNode receiver: receiverGensym selector: receiver value arguments: argsGensyms. ^STInST.RBBlockNode arguments: (argsGensyms copyReplaceFrom: 1 to: 0 withObject: receiverGensym) body: (STInST.RBSequenceNode statements: (OrderedCollection with: messageNode)) Since this transformation occurs at compilation time, via direct manipulation of the source code, Presource can make these "messages" do things that messages can't do otherwise.