The translation phase takes a top-level form (or body), and generates a ModuleExp, which is a top-level expression. This is done using a Translator, which keeps track of lexical bindings and other translation state.
class Translator
{ ...;
public Expression rewrite(Object exp)
{ ... }
public Expression syntaxError
(String message) { ... }
} |
The rewrite method converts a Scheme source form to an Expression. The syntaxError method is called when a syntax error is seen. It prints out the current source filename and line number with the given message.
class Syntax
{ ...;
public abstract Expression rewrite
(Object obj, Translator tr);
} |
The rewrite method in Translator checks for syntactic keywords and macros. If the car of a “call” is a Syntax or if it is a Symbol that is bound to a Syntax, then its rewrite method is called.
As an example, this trivial class implements quote:
class quote extends Syntax
{ ...;
public Expression rewrite
(Object obj, Translator tr)
{ // Error-checking is left out.
return new QuoteExp(((Pair)obj).car);
}
} |
Much more complicated is the Syntax that implements define-syntax.
class define_syntax extends Syntax
{ ...;
public Expression rewrite
(Object obj, Translator tr)
{ enter (new SyntaxRules (...)); }
} |
The result is a SyntaxRules object, which contains an encoded representation of the patterns and templates in the syntax-rules. This is in its own right a Syntax object.
class SyntaxRules extends Syntax
{ ...;
SyntaxRule[] rules;
public Expression rewrite
(Object obj, Translator tr)
{
Object[] v = new Object[maxVars];
for (int i = 0; i < rules.length;)
{
SyntaxRule r = rules[i++];
if (r.match (obj, v))
return r.execute_template(v, tr);
}
return tr.syntaxError
("no matching syntax-rule");
}
} |
Contrast evaluating a procedure definition (lambda), which causes a new sub-class of Procedure to be created and compiled, while evaluating a define-syntax only causes a new instance of SyntaxRules to be created.