Live data from Hacker News

Show HN: My C compiler compiled itself

github.com

21–30 of 130 posts

Re: Show HN: My C compiler compiled itself

#21

Why not use WASM to bootstrap your compiler?

Unlike any real machine (and most virtual ones), WASM is impossible to target with a simple single-pass C compiler. The reducible control flow requirement means you have to build a full control-flow graph and do graph algorithms to it before you can start emitting code. So IMO it makes for a bad starting point.

Re: Show HN: My C compiler compiled itself

#22
post #17
post #12

nice work. if you want more of a challenge try a compiler compiler that can compile itself... :) i got pretty far with this myself, although it doesn't work for weirdo languages like Python that need an exceptional lexer. i keep meaning to revisit this problem, since the tools in this space are pretty much non-existent or trash quality. https://github.com/semiessessi/cp2

> if you want more of a challenge try a compiler compiler that can compile itself... :) Is that not what OP did?

No (if the parent really meant ‘compiler compiler’ which, I think, would be what yacc/bison is).

Re: Show HN: My C compiler compiled itself

#23
post #16

Earlier quoted context omitted.

> Why isn't that also done by the Makefile? My guess is that some people would rather write Python code than dig into Make’s documentation. That said, ChatGPT is excellent at creating valid make files.

Or just take a few moments to learn the basics about Makefiles. The thing about Makefiles is that simples ones at least are really easy to write, and read. Much simpler and quicker than a cumbersome python script, that will most likely do less with much more boilerplate code (e.g. dependencies), and be much harder to read. Of course, you may hit a point where you stretch your Makefile so much beyond its common capabi…

As someone that learned C# and python before C and C++, to this day I couldn't explain to you how make rules work. Make is so unlike build tools from other languages that it doesn't surprise me someone would rather use python to bootstrap their compiler.

Re: Show HN: My C compiler compiled itself

#24

Why not use WASM to bootstrap your compiler?

Unlike any real machine (and most virtual ones), WASM is impossible to target with a simple single-pass C compiler. The reducible control flow requirement means you have to build a full control-flow graph and do graph algorithms to it before you can start emitting code. So IMO it makes for a bad starting point.

If you want to have "fun", generate code in a WASM-representation of Hoare's WHILE language, i.e. a program that only consists of a single outer while loop (in WASM a "loop" block), and conditionally decide for every single instruction in the loop whether it should be executed during a given pass.

I think that could be done with a single-pass C compiler. In a very trivial (and terrible) case, you could keep a running "line_counter" variable that every statement in the loop is predicated with, which either gets incremented at the end of the loop, or set to an arbitrary value for representing branches.

It would of course be a horrible (but very amusing) mess, and rather enforces your actual point.

Re: Show HN: My C compiler compiled itself

#25
post #22
post #17

Earlier quoted context omitted.

> if you want more of a challenge try a compiler compiler that can compile itself... :) Is that not what OP did?

No (if the parent really meant ‘compiler compiler’ which, I think, would be what yacc/bison is).

Ah, thanks. My brain actually did not see that second "compiler" when reading, now it makes sense.

Re: Show HN: My C compiler compiled itself

#26
post #16

Earlier quoted context omitted.

Or just take a few moments to learn the basics about Makefiles. The thing about Makefiles is that simples ones at least are really easy to write, and read. Much simpler and quicker than a cumbersome python script, that will most likely do less with much more boilerplate code (e.g. dependencies), and be much harder to read. Of course, you may hit a point where you stretch your Makefile so much beyond its common capabi…

As someone that learned C# and python before C and C++, to this day I couldn't explain to you how make rules work. Make is so unlike build tools from other languages that it doesn't surprise me someone would rather use python to bootstrap their compiler.

It is so trivial, it takes you 10 minutes to learn.

Less even, here is an attempt:

    foo.o: foo.c
        clang -c -o foo.o foo.c
This builds a file called foo.o, if foo.c is newer than foo.o. Imagine that there is an identical bar.o as well, that builds it from bar.c.

    fooexec: foo.o bar.o
        clang -o fooexec foo.o bar.o
This links together foo.o and bar.o into a file called fooexec, if at least one of foo.o or bar.o is newer (which in turn means that any of its respective dependencies changed; e.g. change bar.c, and bar.o and then fooexec will rebuild).

Now type this into the shell:

    make fooexec
Congratulations! You have a fully built fooexec. Now change bar.c, type it again, and like magic, you have a rebuilt bar.o and fooexec. foo.o will stay put, it’s up to date!

But of course all the .c -> .o rules look the same, so instead of writing a new one for every file, you'd use simple wildcards, and now the whole, entire Makefile is just:

    %.o: %.c
        clang -c -o $@ $
Do $@ and $It pains me if that is not immediately obvious. And it pains me even more that someone would want to write a boilerplate heavy, complex python program, that rebuilds everything all the time, instead of just learning this very simple concept.

Re: Show HN: My C compiler compiled itself

#27

> Then run ./build.py. This will use the bootstrapped 30cc-compiler to compile 30cc itself. It then again uses the 30cc-compiled compiler to compile 30cc once again. The final compiler is then stored as ./30cc. Why isn't that also done by the Makefile? The only catch I could see is that you'd need to have it build to different output names, but that seems fine for what it is? --- Also, I'm curious - did you find your…

> Why isn't that also done by the Makefile? My guess is that some people would rather write Python code than dig into Make’s documentation. That said, ChatGPT is excellent at creating valid make files.

If make is too hard, ninja is simpler. Less powerful but in ways that rarely matter. I've written both by hand both are a little weird but not hard. Normally I use cmake these days (an aweful language but it works for hard problems)

Re: Show HN: My C compiler compiled itself

#28
post #26

Earlier quoted context omitted.

As someone that learned C# and python before C and C++, to this day I couldn't explain to you how make rules work. Make is so unlike build tools from other languages that it doesn't surprise me someone would rather use python to bootstrap their compiler.

It is so trivial, it takes you 10 minutes to learn. Less even, here is an attempt: foo.o: foo.c clang -c -o foo.o foo.c This builds a file called foo.o, if foo.c is newer than foo.o. Imagine that there is an identical bar.o as well, that builds it from bar.c. fooexec: foo.o bar.o clang -o fooexec foo.o bar.o This links together foo.o and bar.o into a file called fooexec, if at least one of foo.o or bar.o is newer (wh…

This is an excellent explanation of make! The only thing I will add is the slightly more abstract thought that make is meant to build files out of other files based on timestamps of the source files. And the target files can themselves become source files, which means that you can build dependency graphs. Lastly, it has “caching” built in: if bar.o is newer than bar.c, don’t rebuild it. If it doesn’t exist or is older, do rebuild it. So when you change one file, you don’t recompile the entire damn tree.

It also has “phony” targets that aren’t files. The canonical example of this is “clean” which basically just does something like rm -rf *.o fooexec

This is what the JavaScript tooling people have been chasing for the past 15 years and can’t seem to grasp. Someone actually did build a make-based JS build system I believe but it never got popular because it wasn’t written in JavaScript.

Re: Show HN: My C compiler compiled itself

#29
post #26

Earlier quoted context omitted.

As someone that learned C# and python before C and C++, to this day I couldn't explain to you how make rules work. Make is so unlike build tools from other languages that it doesn't surprise me someone would rather use python to bootstrap their compiler.

It is so trivial, it takes you 10 minutes to learn. Less even, here is an attempt: foo.o: foo.c clang -c -o foo.o foo.c This builds a file called foo.o, if foo.c is newer than foo.o. Imagine that there is an identical bar.o as well, that builds it from bar.c. fooexec: foo.o bar.o clang -o fooexec foo.o bar.o This links together foo.o and bar.o into a file called fooexec, if at least one of foo.o or bar.o is newer (wh…

Saying this is an 'incremental makefile' isn't really correct, as changes to header files aren't going to lead to rebuilding.

So, either you need to manually keep references to which .h files you include in your Makefiles up to date, or start worrying about M / MM / MG / MP, and of course you'd like those to be re-run when you change your files, and suddenly your Makefile is an awful lot less simple.

This is the main reason I stopped teaching Makefiles in intro to C courses -- students often lost entire afternoons to forgetting this stuff, and failing to realise their mistake. It really shouldn't be any person's job to keep this up to date, when the computer knows it.

Re: Show HN: My C compiler compiled itself

#30
post #25
post #22

Earlier quoted context omitted.

No (if the parent really meant ‘compiler compiler’ which, I think, would be what yacc/bison is).

Ah, thanks. My brain actually did not see that second "compiler" when reading, now it makes sense.

How could you tell the difference between missing it and your brain filtering it out?
Post reply on HN