zot/Leisure

Hygenic macro substitution

zot opened this issue · 0 comments

zot commented

Before macro substitution in an expr, alpha-substitute all variables with gensyms (guaranteeing that all variable names are globally unique). After macro substitution is complete, back-substitute every variable whose original name doesn't appear in the newly substituted expr so that the substituted expr is still (mostly) recognizable.

Use gensyms that cannot be provided by typing, like '[originalName].137' (because '.' is a token).

This will handle the case of shadowing globals that the macro refers to. Macros will use gensyms for names, so that will handle shadowing from the other side.

This is really just applying alpha substitution to macro substitution. Or it's like lexical scoping for variable names as opposed to just their bindings.

This has a few nice properties:

  1. it lets macros be just as simple as LISP's (as opposed to Scheme's)

  2. it lets Leisure use a single namespace for variables and functions, like Scheme and Clojure (as opposed to LISP-2s)

  3. it doesn't require using a package system to avoid global collisions (as opposed to Clojure and LISP-2s), which, as I read it, is only a partial solution to the problem.

My solution is really just applying alpha substitution to macro substitution (yay, Lambda Calculus). I don't see a lot of hits on Google for '"hygienic macros" "alpha substitution"', though, so maybe my solution doesn't work. Or maybe it's not a popular solution. Or maybe no one's actually thought of it. Anyway, I'm going to modify how Leisure does macro substitution and see what happens... :)