clr

dmiller 2025-09-05T20:12:33.765579Z

Having trouble getting to sleep at night? My new series of posts on Clojure compiler internals is just the ticket. Five minutes with one of these and you'll be out for the rest of the night! The title to the series: C4 = Classic Clojure Compiler Contemplation Though these posts are over in the ClojureCLR.Next blog, they analyze the compiler as it exists today in ClojureCLR. Most of this analysis applies equally to ClojureJVM. Intended for the mythical compiler-maintainer-who-will-appear-someday in order to orient them to the structure of the compiler, those with interests in the arcane arts (of compiler design) might find them entertaining. The first five of an intended minimum ten posts are available today. (And the topic of an eleventh post just occurred to me as I was typing this.) • [C4: Classic Clojure Compiler Contemplation](https://dmiller.github.io/clojure-clr-next/general/2025/08/31/classic-clojure-compiler-contemplation.html) - The first in a series of posts analyzing the Clojure (JVM/CLR) compiler. In this post, we look at the overall structure of the compiler. • [C4: AST me anything](https://dmiller.github.io/clojure-clr-next/general/2025/09/01/AST-me-anything.html) - We give a quick overview of all the AST node types used in the Clojure compiler.. We finish with a quick look at Compiler.Analyze, which generates an AST from a form. • [C4: Symbolic of what?](https://dmiller.github.io/clojure-clr-next/general/2025/09/02/symbolic-of-what.html) - We look at the interpretation of symbols in Clojure code. • [C4: ISeq clarity](https://dmiller.github.io/clojure-clr-next/general/2025/09/03/iseq-clarity.html) - How the Clojure analyzer processes an ISeq. • [C4: Functional anatomy](https://dmiller.github.io/clojure-clr-next/general/2025/09/04/functional-anatomy.html) - We look at the implementation of functions in ClojureCLR and how evaluation/compilation translates a source code definition of a function to the underlying class representation. Really, this is only a start. I had to split this into multiple posts. More to come. BTW, if anyone is an expert on Github Pages, Jekyll, the minima theme or some replacement, I could use some help reorganizing this blog. With 40 posts listed in reverse chronological order on the index page, it's getting a bit unwieldy.

👏 1
3
❤️ 6
🙏 2
🙏🏼 1
🙏🏽 1
dmiller 2025-09-06T13:45:27.605249Z

BTW, for those interested in the work on ClojureCLR.Next, I haven't had time yet to start writing it up, but I have written a parser for Clojure in F#. The regular Clojure(JVM/CLR) compiler interweaves AST generation, semantic analysis, and code generation -- and uses some really, gnarly control/data flow to get it done. The F# code I have written is just the parser. The AST node classes are not identical -- there are some that can be differentiated only after semantic analysis. But it is complete. And passes around the parser context in a reasonable manner rather than relying on dynamic binding of Vars all over the place. Take a look here: https://github.com/dmiller/clojure-clr-next/tree/main/src/Clojure.Next/Clojure.Compiler I also wrote tests for the parser, found here: https://github.com/dmiller/clojure-clr-next/tree/main/src/Clojure.Next/Clojure.Compiler.Tests The primary test file is over 3600 source lines, has over 120 test cases with over 340 tests. It is complex; it needs cleaning up. But it does document parsing output and error cases across all the primitive constructs. For example, just for parsing recur -- no semantic analysis or code-generation, just parsing, we have

| test case                                  | parsed code 
| "recur not in a loop -- throws"            |  "(let* [x 7] (recur 12))"
| "recur not in return context -- throws"    |  "(loop* [x 7] (recur 12) 7)"
| "recur with arg count mismatch -- throws"  |  "(loop* [x 7] (recur 12 14))"
|  "recur across try -- throws"              |  "(loop* [x 7] (try (recur 12 14)))"
|  "recur works"                             |  "(loop* [x 7] (recur 12))"
This is just version one of the parser. I implemented this based on the existing compilers for Clojure(JVM,CLR), extracting the pure parsing components. An alternative would have been to base a parser on the tools.analyzer library https://github.com/clojure/tools.analyzer, with add-ons https://github.com/clojure/tools.analyzer.jvm and https://github.com/clojure/tools.analyzer.clr. For those of you for whom the five blog posts listed above do not suffice, I did a deep dive analyzing these tools in two unpublished write-ups: • https://github.com/dmiller/clojure-clr-next/blob/main/docs/tools.analyzer-analysis.mdhttps://github.com/dmiller/clojure-clr-next/blob/main/docs/analyze-tools.analyzer.txt. I think the next version of the parser will try to bring in more of the notions from tools.analyzer. I want to improve code clarity and ease of testing. Stay tuned.

1