Syntactic Types


There are limits to the flexibility of Avail's grammar. For example, variable declarations and blocks have a built-in syntax. If we wish to have the utmost in flexible syntax we will want to define these core syntactic elements in terms of even simpler ones. I believe the solution must involve compile-time transformations. These are called "macros" in traditional languages.

The basic scheme is to implement macros as a variation of methods. The difference is that they execute at compile time (at call sites). This is similar to the NLambda and MLambda expressions from Scheme. Instead of passing values as arguments to these macros, we pass parse trees, the only things available at compile time. The macro then answers another parse tree as its result, one which will be spliced into the code being compiled in place of the invocation of the macro. Here's a sketch of an example that I had in mind...

Macro "For_in_do_" [
        varExpr : Variable Node,
        tupleExpr : Expression Node,
        bodyStmt : Statement Node |
    Send Node
        message (lookup "_do_")
        arguments ;
];

For x in <10,20,30> do Print x;

So eventually I could define "_:_" for declarations, "_:=_" for assignments, "[_]" and "[_]:_" for blocks, "$_" for label declarations, "&_" for reference expressions, and even "_;" for statements (that one would take some serious thought first). I might even be able to generalize the lexical scanner (so the syntax of tokens can be defined within Avail), but that's not as important at this time.

These things would allow pretty much any syntax at all to compile to Avail code with well-defined semantics. And the whole compiler would be written in Avail. And modular. And the generated code would run on top of the Avail VM, wherever that happened to be ported. And code written in differing syntaxes would be as interoperable as the underlying datatypes would allow.


A slightly different alternative scheme would be to use the regular defining method "Method_is_" instead of introducing a new "Macro_is_" method. Then the types of the formal arguments could be the signal to do macro expansion versus runtime method lookup. If an argument was a subtype of Parse Node (a sibling of "all" and "list", under void), then the method definition would be treated as a macro.