The first line is redundant given the second one; struct ASTNodealready names the incomplete type. So you can just keep the second line and elide the first.
Thanks! This was cut & pasted from a more advanced version of the compiler which had some intermediate datatypes in the middle (cons, etc) that referenced struct ASTNode *.
Why did you remove your other comment? Sorry, I hadn’t gotten around to reading & replying yet.
This series is off to a good start. I’m interested to follow it… most Build Your Own Lisp type projects use a virtual machine instead of compiling down to native code.
I wrote a series last year on compiling a lisp to amd64 assembly in JavaScript. Unlike this series mine is on AOT, not JIT compilation. In the series I explored simple register-based usage of amd64, LLVM, and ultimately another variant of amd64 using it more solely as a stack machine.
You can find decent amount of info from existing languages. Just look up “object representation” in Chicken Scheme, Python, OCaml, V8, etc. I was always told though that the memory scheme doesn’t actually matter a whole lot overall so you can just do whatever reasonable representation you think of. Then again, there’s a lot of discussion you can find on optimizing OCaml’s number representation so of course you can optimize too.
That was very interesting and well explained, I’ve always wondered how does a JIT compiler actually work but never bothered to find out.
You got me excited for the second part!
Here are two other great intros I always fall back on:
Well it’s your lucky day! I got bored this morning and wrote about compiling integers.
The first line is redundant given the second one;
struct ASTNode
already names the incomplete type. So you can just keep the second line and elide the first.Thanks! This was cut & pasted from a more advanced version of the compiler which had some intermediate datatypes in the middle (
cons
, etc) that referencedstruct ASTNode *
.Why did you remove your other comment? Sorry, I hadn’t gotten around to reading & replying yet.
This series is off to a good start. I’m interested to follow it… most Build Your Own Lisp type projects use a virtual machine instead of compiling down to native code.
I wrote a series last year on compiling a lisp to amd64 assembly in JavaScript. Unlike this series mine is on AOT, not JIT compilation. In the series I explored simple register-based usage of amd64, LLVM, and ultimately another variant of amd64 using it more solely as a stack machine.
You may be interested: https://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html
Thanks for this! I’ll definitely be reading this later today.
I think we solved basically the same problem except that you are using an external assembler and linker to generate the ELF file for you.
Well fundamentally I’m not JIT compiling (writing and executing memory in the same process) but yeah other than that the two are similar.
Oh, I think there’s our linguistic difference. I draw the line in a different place:
AOT: Compile the whole program to the target architecture. May or may not include disk I/O.
JIT: Compile the pieces you need, when you need them, and probably have some kind of inline caching and inlining.
Indeed I am interested. Thank you, will look at your series too.
Where do you get all these Lisps with VMs? I seem to find only tree-walking interpreters.
Lisp in Small Pieces was the one I had greatest hopes for.
The Lisp System Implementation book similarly targets a vm.
Good start! Looking forward to the rest.
[Comment removed by author]
You can find decent amount of info from existing languages. Just look up “object representation” in Chicken Scheme, Python, OCaml, V8, etc. I was always told though that the memory scheme doesn’t actually matter a whole lot overall so you can just do whatever reasonable representation you think of. Then again, there’s a lot of discussion you can find on optimizing OCaml’s number representation so of course you can optimize too.
Future picolisp implementation on LLVM-IR — https://github.com/picolisp/pil21