Friday, February 18, 2005

Compile-time environments

PLT maintains a phase separation between macro expansion and program evaluation. The first phase is known as macro elaboration-time, and the latter as runtime. The runtime contains a normal environment mapping variables to values, but at elaboration-time, there are two environments at work:
  • the syntactic environment, which binds identifiers to their static behavior for the macro expansion algorithm, i.e., whether the identifier is mapped to lambda, let-syntax, or a macro (etc.) -- identifiers are bound in this environment by define-syntax, for example.
  • the transformer environment, which is a regular Scheme evaluation environment, but exists during the elaboration phase, not a runtime -- identifiers are bound in this environment by define-for-syntax, for example.
The syntax-local-value procedure allows you to get at the mapping of an identifier in the syntactic environment. If you define a structure type my-struct, the define-struct macro expands into a new define-syntax that binds my-struct to some static information about the structure type that you can get at with (syntax-local-value #'my-struct). You can't really change this information (short of hacks with macro-redefinition, which tend to be brittle), because the syntactic environment is rather jealously guarded by the macro expansion algorithm. If you want to maintain more flexible and complicated information at elaboration time, that should go in the transformer environment.

No comments: