Skip to content

Commit 00e31f5

Browse files
committed
Slight edit to AOT post
1 parent 9b1fdbb commit 00e31f5

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

_posts/2025-02-20-AOT-compilation-issues.md

+17-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,24 @@ If the 'save it into a memory stream ... then load it back' sounds promising, um
104104

105105
## How to proceed
106106

107-
The only solution I've come up with so far is doing all the code generation twice. Syntactic and semantic analysis -- the generation of the AST from which we do code generation -- need only be done once. For each form, we then create two types, one in the `eval` dynamic assembly and one in the persisted assembly that we will save to file. We generate code into each type and evaluate the one from the dynamic assembly.
107+
The only solution I've come up with so far is doing all the code generation twice.
108+
Syntactic and semantic analysis -- the generation of the AST from which we do code generation -- need only be done once.
109+
For each form, we then create two types, one in the `eval` dynamic assembly and one in the persisted assembly that we will save to file.
110+
We generate code into each type and evaluate the one from the dynamic assembly.
108111

109-
It might work. But there are complications I have not figured out yet. For example, consider direct linking. Without direct linking, the following code
112+
Even this is not as easy as it sounds. (If it sounds easy.) The design of the current compiler has code generation happening _during_ syntactic analysis.
113+
Specifically, those things that are 'functions' -- typically what you get from `defn`, `deftype`, raw uses of `fn`, etc. -- actually have their types generated and finalized during the first pass.
114+
It even goes a little further. If you do something at the REPL (or in a source file) such as:
115+
116+
```clojure
117+
(def x (let [y f(12)] (inc y)))
118+
```
119+
120+
it so happens that 'naked' `let`s get wrapped with a `fn` -- don't ask -- so even in something as simple as this, we have a type generated during syntactic analysis.
121+
I _think_ that this very little effect at that point in the process -- but I might have to do double generation even during syntactic analysis.
122+
(Note: One of rationales for the ClojureCLR.Next project is cleaning up the compiler design.)
123+
124+
Anyway. Emitting twice, once for saving and once for progressive evaluation, might work. But there are complications I have not figured out yet. For example, consider direct linking. Without direct linking, the following code
110125

111126
```clojure
112127
(defn f [x] (inc x))

0 commit comments

Comments
 (0)