4 ms·
As someone who has been designing a language since late 2012 (and it's about to have its first public release early next year O.o), here are some thoughts. Avo
by gavinhoward 3y ago
As someone who has been designing a language since late 2012 (and it's about to have its first public release early next year O.o), here are some thoughts.
Avoid gradual typing: Absolutely. I had gradual typing and abandoned it. Gradual typing is not as good as simple Go-like inference, and that simple inference is easy to implement and takes care of 95% of the "problem."
However, you also need one or more dynamic typing escape hatches. When I implemented a config file format by tweaking JSON, I had to implement dynamic typing in C.
Avoid self-hosting your compiler: It depends. You probably should avoid it by default, unless your language is just so much better than the original. Rust is an example of this (compared to C++). I'm writing in C, and I want memory safety [1], so bootstrapping makes sense.
Avoid writing your own code generator, linker, etc.: This is excellent advice! Use the standard tools. Of course, me being me, I'm breaking it. :) I am trying a different distribution method, where you distribute an LLVM-like IR, and the end machine then generates the machine code on first run. In that case, there's no linker necessary, but I do have to write my own code generator. Fun.
Avoid bike shedding about syntax: Yes, absolutely. I did this, but the syntax still changed enormously!
Cross-platform support is a challenge: Yes, in more ways than one. First, you have to somehow generate code for all of the platforms, then you have to make sure your library works on all of the platforms too.
Compiler books aren't worth the money: Yes, but please do read Crafting Interpreters. Anyway, getting a simple parser and bytecode generator (or LLVM codegen) is the simple part of making a language. Then you need to make it robust, and no one talks about that. Maybe I should write a blogpost about that once my language stabilizes.
Growing a language is hard: Yes, absolutely. He mentioned two ways it needs to grow: libraries and users.
You can design a language to be easy to grow via libraries. See "Growing a Language" by Guy Steele. [2] I went the extra mile with this, and user code can add its own keywords and lexing code. So growing my language is "easy."
But growing the userbase? That's hard. You need to have a plan, and the best plan is to solve a massive pain point, or multiple. I'm targeting multiple.
First, I'm targeting shell; my language can shell out as easily as shells, or even more easily, but it's a proper language with strong static type checking. If there are people who want that instead of bash, they'll get it. And there's a lot of bash people might want to replace.
Second, I'm targeting build systems. My language is so easy to grow, I've implemented a build system DSL, and then I put a build system on top.
Shell and build systems are both things people hate but use a lot. These are good targets.
The best test suite is a real application: Yes, absolutely. Except, the best test suite is actually a bunch of real applications.
My language's own build scripts are the first real program written in it. I'm also going to replace every shell script on my machine with my language, and most of them will make it into the formal test suite.
Don't prioritize performance over functionality: Yes, absolutely. This is why I would suggest making an interpreter first; you don't depend on LLVM (shudder), and you can easily add functionality.
Building a language takes time: I've taken 11 years, and there's no release yet. Yes, this is true.
cries in the corner
Anyway, I wish the author luck, even though I'll be a competitor. :)
[1]: https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-in-memory-safety/ https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-i...
[2]: https://www.youtube.com/watch?v=lw6TaiXzHAE https://www.youtube.com/watch?v=lw6TaiXzHAE