(WIP) A C backend for PureScript

I’ve been working on a C backend for PureScript over the last couple of weeks with great success so far. I’m almost half way through implementing the FFI for the purescript-prelude package at the moment, exercising the backend along the way. I am about to tackle Data.Functor, something I had been looking forward to for a while :slight_smile:

The project lives on github over here: https://github.com/felixSchl/purescript-c.

I’ll set up a proper README in the near future with instructions on how to build the project, but will likely revisit the way compilation occurs anyway (e.g. compile the runtime library to it’s its own shared object and then link against it downstream etc.). If you’re interested in contributing to make this project a reality, collaboration and set up should be easy and there’s plenty of work to do, so don’t be put off by how the README looks - it’s all early days.


I’m not too knowledgeable about C/C++, so I may be asking a dumb question – have you seen Pure11? If so, how is your project’s goal different than Pure11?

Yeah I have seen Pure11 and actually started off porting that code to PureScript in order to detach it from the PureScript codebase. The goals are probably fairly aligned. The Pure11 project was a good place for me to get started in understanding the corefn representation and how code is emitted. When time came for me to understand the runtime cpp stuff, however, I quite frankly could not develop a genuine interest to understand all this complicated C++ syntax and wondered if it was really necessary. Finally, since it wouldn’t have been a straight port (project appears to have fallen behind PureScript codebase and libraries were not updated), I figured I might as well have some fun and try emitting C instead.

Even with the existence of the C++ backend, I think a straight C one is worth exploring (I’ve been tempted to do one myself a few times). They can end up having different strengths and weaknesses, and really, if the C one ends up more useful all-around and supersedes it, then that’s still good for everyone.

I have recently found some time to update (actually re-do) the C++ backend, but I haven’t announced it yet. Also, I agree that the old runtime was too complicated – it was done that way for execution speed, but I ended up wondering if it was worth it. The new version is less efficient, but much simpler to understand.

Forking the compiler was also a pain, and the new version now uses the output from purs --dump-corefn instead: https://github.com/andyarvanitis/purescript-native/tree/native-dump-corefn. It’s still in Haskell and not PureScript for now, but I’d like to switch over once bootstrapped with the new approach.


Update: I’ve implemented the FFI for the complete Prelude, and enough of the Effect FFI to demonstrate usefulness. The latter allowed me to put the GC mechanism through some heavy testing - so the last couple of my days I pretty much spent with SIGABRT and it’s pal SIGSEGV. @andyarvanitis It would be cool to get your opinion on this: I currently have a cycle in the GC where a scope would keep all it’s bindings alive, including any blocks (lambdas), but the blocks themselves must keep the scope alive, including themselves. I wonder if, and how, I can break this cycle as it would currently prevent collection from happening.

Sweet, I found a way to do this by freezing the captured bindings at the time the block is introduced. This means it cannot reference any bindings that occurred after it, however, so I need to test this a bit further (maybe the corefn is already laid out in dependency order?)

@felixschl Great, glad you found a solution! Sorry I didn’t get back to you sooner. I do hope to have a peek at your handiwork sometime soon.

Yes, I think things in corefn are in dependency order, but you do have to handle mutually recursive lets, so that’s something to look out for.

Would love some help with this https://github.com/pure-c/pure-c/issues/20 - GC issues under clang compile optimizations. I have no clue where to start even. It’s not pressing, but knowing what’s causing it would put my mind to ease the problem does not generally exist somewhere else.