Presource design and overriding the Smalltalk parser

Tagged:  •  

Paolo writes that he's looking to remove the capability to override the parser for a Behavior's methods from strings passed to #compile:, as well as old-syntax method definition lists, by moving #parserClass to CompiledMethod. He mentions that Presource fares quite well with this restriction, providing full message macros just by overriding the compiler.

For those not well-versed in Presource architecture, Presource adds a "code mindset" to all classes. It also provides a compiler that uses the code mindset to make structural changes to parsed Smalltalk source before passing it on to the STCompiler. It never touches the parser, which is why it works unchanged even though the parser was replaced in 2.95e.

It's not that I have something against overriding the parser; it's just that I carried my mental model of macros (sans reader macros) from Lisp. In Lisp, they work because you have data structures representing the code, not because they are specialized just for representing Lisp code; code is primarily represented using generic pairs and symbols, whereas in Presource we operate on RBProgramNode instances. Furthermore, there are fewer rules in the Lisp read syntax than Smalltalk parseable syntax, which makes this a more reasonable proposition for Lisp than Smalltalk.

I actually considered providing an "array form" for macros, where messages could be specified like {#at:put:. recv. arg. arg2}, but CodeTemplate and PatternMacro have sufficed for now. In addition, I say from experience that sending messages to RBProgramNode classes is a frightfully verbose way to construct macro expansions.

Whether my decision to maintain the purity of Smalltalk syntactic rules in Presource provides a sufficient platform for developing "little languages" will be revealed as more conceptual expressions are smooshed into these "little languages" defined by Presource message macros.

Incidentally, Presource presents its compiler by changing #compilerClass to look for the 'Compiler' global variable in the behavior's namespace or superspaces, falling back on STInST.STCompiler. Then, the code mindset installer for namespaces makes sure that the namespace has something like its compiler in the 'Compiler' variable. I chose the name 'Compiler' because it is the traditional name for a Smalltalk compiler in an ST-80 image; I would like to hear feedback on this choice.

> I say from experience that sending messages to RBProgramNode
> classes is a frightfully verbose way to construct macro expansions.

Yes, it would be great to have a method like RBProgramNode>>#from:with: which would work like this:

makePlus: arguments
    RBProgramNode
         fromTemplate: '`var1 + `var2'
         with: { 'var1' -> arguments first. 'var2' -> arguments second }

Or for better speed (avoiding to reparse the template every time):

makePlus: arguments
    ^##(RBProgramNodeTemplate from: '`var1 + `var2')
        with: { 'var1' -> arguments first. 'var2' -> arguments second }

The latter is the CodeTemplate class in Presource, which simply makes #copyInContext: and #match:inContext: easier to use with the #match: and #expand: methods.

User login