Hacker Newsnew | past | comments | ask | show | jobs | submit | codr77's commentslogin

Lisp is a better choice than most for the first compiler/interpreter, but I would recommend starting even further down the complexity scale with Forth [0] since it lowers the risk of running out of motivation/loosing track of the goal.

[0] https://gitlab.com/sifoo/snigl


I think Lisp is a great choice for a first interpreter, but a hard one for a first compiler. Macros make the separation between "compile time" and "runtime" really squirrely. For a first compiled language, I would do something like Pascal.

But, personally, I would really like to write a compiler for a Lisp specifically because I find the handling of macros really confusing and I don't think I'll understand it better until I actually do it.


In the usual design, Lisp compilers begin their job when macro-expansion is done; the input is fully expanded code with no more macros to be invoked. This separation is crystal clear; nothing squirrely about it.

If you boostrap a Lisp compiler by writing a Lisp interpreter first, with macros and all, then there is nothing left to do, macro-wise, when you set out to make the compiler.

You can freely use macros in that compiler's own source code, too.

There is an interaction between macros and compiling in the larger picture. When you have a working compiler and you integrate it into a file compiler, now your macros are executing at a bit of a different time: when your file compiler reads a file of code, it has to run the macros to expand it. Then when the compiled code is loaded, the macro calls no longer exist. The compiling happens in the development environment, whereas the loading may be in the deployed environment which may be a completely different system. So macros that assume they are executing in the production environment (due to being interpreted) are in for a rude surprise: they are now run in the build environment due to the shiny new compiler. That kind of thing can introduce "squirrely" issues.

Another squirrely issue is: what is a "top-level form". Suppose we have

   (progn (defmacro foo ...) (foo ..))
if the (foo ...) call is to be able to refer to the definition, that definition must be evaluated so that it takes effect! But that means that evaluation must be interleaved with macro expansion to some extent; we can't just expand the whole (progn ...) all at once.

The way out of this is to have requirements like: (1) any form not enclosed in another form is a top-level form and (2) if a (progn ...) is a top-level form, then its constituents are considered to be individual top-level forms, and (3) each top-level form is individually macro-expanded and compiled/evaluated.


Scheme is wayyyy simpler than Forth IMO (even when you include macros and call/cc). I wrote a minimal stack-based language years ago and I still cannot get a handle around Forth. The inner interpreter and immediate words? Even after reading Let over Lambda, Forth is greek to me.

But, to be fair, getting to the point of being able to implement a recursive fibonacci algorithm is not too difficult taking either path.


Forth is really a kind of assembly language for a virtual machine, and not really a higher level language. It looks higher level because it doesn't have registers.

Register machine languages are "catenative" also. We can take a "mov eax, ebx" and catenate that with "move ecx, $foo" in any order we want. We are constrained, though, because different sections of code use different input and output registers (or combinations of input and output registers and stack locations and such). Forth makes those conventions uniform, and that leads to some degrees of freedom which give it a higher level flavor.

The thing to do is to make some higher level language that uses Forth as a VM; then you have understandable code.


I mean simple as in primitive and easy to implement.

Using Forth effectively takes practice, but I found it worth the effort for the much the same reasons as Lisp.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: