I took the essence of closure conversion and implemented it as a single file racket script with explanation in comments and examples.
The idea is that this should help someone if they are a beginner wanting to implement a language that has lambda. Or anybody who is curious how a compiler might implement lambda.
Lisps look so magical. I wish it were more accepted in the web application industry to pick a lisps for implementing services. I love my Ruby, and my Go, but it would be fun to experiment with a lisp some time.
It's in my own Scheme variant, I'm afraid. I guess I should translate it to something people know. But, for example
;; Variable reference
(to (var-ref<- v)
(make ({.free-vars} (set<- v))
({.compile s k} (cons (s v) k))))
turns a source-code variable access into an AST object with two methods: 1. The free-variable set of this AST has just that one variable. 2. To compile this to bytecode, given a scope s and following code k, ask the scope what instruction to emit for this variable, and prepend that to k. (In general k is passed in for the sake of tail-call optimization, on line 33.)
this is just a tiny nitpick but I'm wondering why you didn't use pattern matching? if you just wanted to stay schemey then disregard but you could skip the entire shapes section and the rest of the code would still be terser, e.g.
((begin? exp)
`(begin . ,(mapply cc (cdr exp) sc)))
The idea is that this should help someone if they are a beginner wanting to implement a language that has lambda. Or anybody who is curious how a compiler might implement lambda.