| author | Alan Dipert
<alan@tailrecursion.com> 2026-01-02 20:24:45 UTC |
| committer | Alan Dipert
<alan@tailrecursion.com> 2026-01-02 20:24:45 UTC |
| parent | e4a58550a4b8065cbfc84deeff7d41de1ae10ca6 |
| md/Lisp/DestinationDrivenCompilation.md | +24 | -1 |
diff --git a/md/Lisp/DestinationDrivenCompilation.md b/md/Lisp/DestinationDrivenCompilation.md index e3d7894..03d7d5b 100644 --- a/md/Lisp/DestinationDrivenCompilation.md +++ b/md/Lisp/DestinationDrivenCompilation.md @@ -1,4 +1,6 @@ # DestinationDrivenCompilation +- Created Thursday 1 January 2026 +- Updated Friday 2 January 2026 (added IR examples) Compilers that target hosts with a hard statement/expression split (JavaScript, C, and similar "bracket" languages) have to respect where values are allowed and where only effects make sense. ClojureScript's emitter handled this with context-sensitive emission: every node got an expression-or-statement flag and picked a matching output form. I patterned [JACL](https://tailrecursion.com/git-arr/r/jacl.git/) after that mode because it kept the emitter easy to read while the backend was taking shape. (See the [ClojureScript emitter](https://github.com/clojure/clojurescript/blob/515900f9762102987bda7d53b919dafc0b6c0580/src/clj/clojure/cljs.clj) `:context` handling.) @@ -16,12 +18,23 @@ Destination-driven compilation (value/effect/tail) - Reduces temps: only value destinations introduce locals, so fewer temps appear and less dead code needs removal. - Propagates destinations: children inherit the current destination and can short-circuit—effect destinations can drop unused values, and tail destinations emit the final `return`. -Example: compiling a value-binding `if` +Example: compiling a value-binding `if` in statement position +The IR sketches use tagged s-expressions; `ctx` shows the expression/statement flag carried on each node, and `dest` marks the value/effect/tail destination threaded through the tree. Source (Lisp-ish): ``` (let [x (if test (f) (g))] (h x)) ``` +Context-sensitive IR (expression mode needing a value): +``` +(ctx :stmt + (let-binding x + (ctx :expr + (if-expr (ctx :expr (var test)) + (ctx :expr (call f)) + (ctx :expr (call g)))) + (ctx :stmt (call h (ctx :expr (var x)))))) +``` Context-sensitive emission (expression mode needing a value): ``` var x = (function(){ @@ -30,6 +43,16 @@ var x = (function(){ })(); h(x); ``` +Destination-driven IR (value destination): +``` +(dest :effect + (let-binding x + (dest :value + (if-node (var test) + (dest :value (call f)) + (dest :value (call g)))) + (dest :tail (call h (var x))))) +``` Destination-driven emission (value destination): ``` var x;