-
tags :: LispDialDial implementationRust
In implementing a Lisp, there is the problem of scope and closure.
Memory efficiency
Since we are making a programming language, we'd want our language's interpreter
to be as efficient as possible1 Therefore we should try to reduce cloning
data as much as possible. This could be achieved with the use of RefCell
in
Rust.
Scopes
How do we deal with scoping in general? Consider the following:
(def x (fn (a) + a 10)
How do we implement this without a
conflicting with something at a higher
level?
Possible solutions
Recursive env
MAL and Risp define an env as such, essentially:
struct Env { bindings: HashMap<String, Val> outer: Option<Env>, }
There are a couple of concerns I have with this. Once you start introducing lifetimes, this becomes quite complicated.
Flat table
Lisp in Small Piecesimplies that one way to store variables would be to store them all in the same place as one collection. This would perhaps make lookup more complicated.
struct Env { bindings: HashMap<String, Binding> } struct Binding { val: Val, scope: usize, // (ref:scope) }
Here (scope)would be a reference to something that provides information about how it could be accessed. This might make memory management simpler but would make lookup complicated, as each scope would need to know:
-
its own ID
-
its parent ID
-
if its a valid reference
-
what values shadow it
These problems can be sidestepped with Recursive =env=
Tail-call problem
If our interpreter is rewritten to essentially be one big while
loop, scope
and garbage collection becomes a problem.
At the end of each iteration of the loop, we need to clear any values that
should go out of scope. For example, if our eval
function evaluates the
following:
((lambda (a b) + a b) 1 2)
We would need a
and b
to not live beyond the lambda
and have the lambda
not persist after its evaluation.
Footnotes
1Ideally Dial will compile to machine code as well, where this will hopefully be less of an issue.
- public document at doc.anagora.org/20210403130020-implementing_lisp_scope_and_closure
- video call at meet.jit.si/20210403130020-implementing_lisp_scope_and_closure