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

https://github.com/rui314/9cc/blob/882e4b2dd8/main.c#L7

    int main(int argc, char **argv) {
      ...

      Vector *tokens = tokenize(path, true);
      Program *prog = parse(tokens);
      sema(prog);
      gen_ir(prog);

      if (dump_ir1)
        dump_ir(prog->funcs);

      optimize(prog);
      liveness(prog);
      alloc_regs(prog);

      if (dump_ir2)
        dump_ir(prog->funcs);

      gen_x86(prog);
      return 0;
    }
This is wonderful.


FWIW I started this thread several months ago to advocate that people write their compilers like this :)

https://www.reddit.com/r/ProgrammingLanguages/comments/89n3w...

In many compilers, including some linked on that thread, this clean structure gets lost.


And also wonderfully devoid of error-handling, too. It's the most common way for beautiful-looking C code to look beautiful.


A compiler is in the happy position where there is little point in continuing to run after encountering an error, so it can bail right out with exit(2) after reporting the error to the user. This means that the contract on parse(), for example, can be that if it returns, it has succeeded.


Except of course LLVM has proven the value in not assuming this pattern & building your compiler as a library of which the executable entrypoint is but one frontend.


Exceptions are the exit() of libraries. Or if you're using plain C, setjmp/longjmp might be a good idea, depending on what you're doing.


Unless the programmer uses the null object pattern in which case everything is hunky dory. For example, an empty "Program" would probably do the job.




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

Search: