* Engineering a Compiler: https://www.amazon.com/Engineering-Compiler-Second-Keith-Coo...
* Modern Compiler Implementation in ML: https://www.cs.princeton.edu/~appel/modern/ml/
* Compiling with Continuations: https://www.amazon.com/Compiling-Continuations-Andrew-W-Appe...
http://www.amazon.com/Compiling-Continuations-Andrew-W-Appel...
and Modern Compiler Implementation in ML:
https://www.cs.princeton.edu/~appel/modern/ml/
There's a certain kind of equivalence between continuations and SSA. Mostly, I bring that up because if you go down the rabbit hole of designing a compiler in C, you'll find talk of SSA, but continuations are somewhat advantageous for designing functional compilers. If you're just looking to design an interpreter, Ben Pierce's book Types and Programming Languages does a good job at showing how to put together a simple functional language both theoretically and practically:
http://www.amazon.com/Compiling-Continuations-Andrew-W-Appel...
This book goes into some of the more advanced uses of macros and I don't believe most carries over to other "lisps".
I really loved the section on reader macros!! That's a topic that doesn't get enough attention from people coming to common lisp.
I don't believe clojure, for example, supports user defined reader macros, atleast I can't remember it having them the last time I used it(circa 2011).
EDIT, it looks like clojure does have reader macros now. Clojure just keeps getting better:)
http://en.wikibooks.org/wiki/Learning_Clojure/Reader_Macros
In addition to Let over Lambda, my common lisp reading list includes:
http://www.amazon.ca/Lisp-Small-Pieces-Christian-Queinnec-eb...
http://www.amazon.ca/Compiling-Continuations-Andrew-W-Appel-...
and http://www.amazon.ca/Paradigms-Artificial-Intelligence-Progr...
I'd love to hear if anyone else has book recommendations in a similar vein. I'm in the middle of a month off to read books and research papers so this is pretty timely for me:)
There is still a lot that has changed since then. In particular:
1) Control-flow analysis has become much more well-understood, and there's a lot more you can do in your optimization phases to dramatically speed up code and reduce allocations (allocations and heap accesses are the bane of functional language implementation, btw. Unless you're Haskell, and then you also have to deal with mutation for shared lazy computation results).
2) Certain tricks such as monomorphisation (http://mlton.org/Monomorphise ) dramatically improve the ability of the compiler to generate optimized code from originally polymorphic inputs without paying huge representation overheads.
Unfortunately, #1 and #2 are mainly written up "in the source" of modern functional language compilers or at best in JFP (Journal of Functional Programming) articles :-( But the Appel book provides most of the fundamentals you'll need to get bootstrapped with anything more modern, so I'd recommend it anyway!
https://www.amazon.com/Compiling-Continuations-Andrew-W-Appe...