Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I had to read twice to make sure I understood correctly: this guy wrote a C-to-Lisp compiler. That's something you don't see every day.


Wow, yeah, I'm glad I failed to talk him out of it!

Still, looking at his list of "big things that need to be done" -- this is not yet a general-purpose C compiler.

I should have asked what his goals for the project were. If he wants a compiler that handles all of C and produces code good enough that people would actually want to use it -- say, within a factor of 5 of optimized GCC output -- I think it's still clear that that's a huge project. But if he just wants to port hardware drivers, which appears to be his primary purpose, yeah, I can see that that might not be so hard. Driver code tends not to use the whole language, though it can do some weird low-level stuff like pointer type punning that can be hard to model in CL. And performance is probably not critical for most drivers since they do little computation.


Actually, I started working on one this past weekend as an exercise. The only real work is the front-end; your Lisp compiler itself can serve as the back-end.

It's not all that shocking; Prolog-in-Lisp is a common exercise, and in Let over Lambda there is a chapter about Forth-in-Lisp.


I think parent was more surprised by the idea that one would want a C-to-Lisp compiler, given that Lisp is more pleasant to write than C and C is usually more performant.


The problem with C-in-Lisp, though, is modelling the low-level behavior of C using the high-level concepts of CL.

Case in point: pointer punning. Somebody takes a 'char ', writes some stuff through it, then casts it to an 'int ' and starts reading that stuff back. ZetaLisp, having been built to implement the Lisp Machine OS in, had some low-level features that made this kind of thing doable, but those features did not make it into Common Lisp (I'm thinking of displaced arrays with mixed element sizes, though as I write this it occurs to me that it might be possible to coax an open source CL implementation into dealing with this, if you can give up on the generated code being portable CL).

If you want to look at Zeta-C, the sources and some commentary can be found here: http://wiki.alu.org/Zeta-C


The C standard doesn't actually require as much from the implementation as you might think. Pointer arithmetic and comparison is only defined for pointers into the same array object (including one past the end), so it's completely possible to implement C with bounds-checked fat pointers. The most painful requirement is probably that there is a sufficiently large integral type to represent pointers across round-trip casts. In portable CL that would require you to track all allocated objects with a unique identifier or implement your own heap.


> Case in point: pointer punning. Somebody takes a 'char ', writes some stuff through it, then casts it to an 'int ' and starts reading that stuff back.

That's only a problem when the "stuff" is indeed machine-specific bytes and not something that has type tags already. That happens when you're writing binary data from memory and reading it back in again, and mmaping files, neither of which is portable C code. There are some rules about ints being a larger number of storage units than chars in the C standard, which Vacietis does violate (everything aside from arrays and structs is 1 storage unit), but aside from that the two use cases I mentioned aren't actually required to be supported by C compilers, and they're surprisingly not frequent.


Yeah, the "back-end" is basically 3 pages of code. Most of the C control structures can be implemented with PROG.



Yeah, I was surprised as well. Curious to know where it's used.




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

Search: