4 ms·
Making your own programming language is easier than you think (but also harder)
- jdw64 6mo ago[dead]
- smitty1e 6mo agoIf I were to make my own programming language, it would look an awful lot like Python. Roughly 100%.
- cornholio 6mo agoI agree, Python allows anyone to write bad code, but makes up for it by running the code slow enough that it can't do real damage.
- tzot 6mo ago> > If I were to make my own programming language, it would look an awful lot like Python. > I agree, Python allows anyone to write bad code, but makes up for it by running the code slow enough that it can't do real damage. In the same sentence you agree with the implied beauty of the syntax of Python and then go on sarcastically about the performance of CPython. Assumably you deliberately mixed language and implementation because you needed a soapbox, so hey, here's my comment to which you can reply and continue your rhetoric.
- cornholio 6mo agoIt's a joke. But you got it all wrong, it's not praise + sarcasm, it's double sarcasm.
- tzot 6mo agoYou say all wrong and then go on about explaining I'm half wrong. I feel there's a pattern (or maybe another joke that whooshed over my head) here but it is obvious to me that I am not your intended stand-up comedy audience and I should ask for my money back. :)
- wildzzz 6mo agoIf someone smarter than me didn't think to invent a new language to solve what is likely a common problem, the solution already exists.
- applfanboysbgon 6mo agoIt is absolutely not the case that all problems worth solving are solved already. Programming language development isn't necessarily about being a genius but rather a willingness to put in a monumental amount of work. Writing a language that compiles is easy enough. Getting a language off the ground to an actually useful place is tedious, simply in terms of the sheer amount of work to be done. Specification, implementation, documentation, diagnostics, optimization, configuration, tooling support, and creating a standard library (especially a cross-platform one) are things that will mire you in many hundreds of hours of work.
- imtringued 6mo agoThose are the easy parts actually. You're thinking of them in terms of time spent, which is not a bottleneck at all. That's an illusion. You need to be a genius, not in the sense of having a high IQ, but rather a genius in the sense of having great ideas. All your competitors are doing the ecosystem marathon, that's not a differentiating factor since your new language will always have a weaker ecosystem unless your language has concepts or features that negate the value of existing ecosystems. If you have a programming language that makes people 10% more productive, then people will have to spend 10x the time to use your language than it took you to develop it for it to break even. Increasing the amount of effort spent on the language moves the payoff further away. Your two key goals are developing a more effective technology and to convince people to use it. This means that differentiating features are critical here. Differentiating features are not present in the old ecosystem, which turns it into a burden rather than a benefit.
- Twey 6mo agoEven the _design_ of languages is a generational project. There are open problems in the PL space that we know need to be fixed but we have no idea how. Once you've got the ‘core ideas’ of the language in some papers somewhere (and proofs that they're coherent, which is usually the meat of the process) it's a pretty quick step to get a toy implementation, but then the path to an implementation that is usable for day-to-day work (especially if performance is important) can take decades, and the path to adoption after that can easily take between 5 and 20 more years. Then people figure out the thing about your core ideas that gets in the way when writing the kinds of real-world programs they want to write and you get to go back to the drawing board for the next language idea :) As an example of the kind of time scales involved, linear logic was introduced in 1987. Linear (well, affine) types made it into Rust 1.0 in 2015, which IMO is the first time substructural types have made it to a ‘mainstream’ (albeit still far from ubiquitous) language. And that's a very straightforward language feature that doesn't really challenge the dominant imperative/functional hybrid paradigm or have any inherent effect on performance (since it's ‘just’ a type system feature). IMHO the next big thing up (assuming LLMs and other AI advancements don't throw everything off-kilter) is probably effect systems, introduced in ~2013, for which we can linearly extrapolate a time frame of about 2041! But maybe not — one exciting thing that's been happening is that (as Jonathan Blow noted) with the growth of lower-level substrates like LLVM the work to go from a toy to a working and performant language has decreased significantly.
- cheschire 6mo agoYeah except my version would only accept tabs instead of allowing (and even encouraging!!) spaces for indentation.
- tzot 6mo agoI see that and I raise Elastic Tabstops! https://nick-gravgaard.com/elastic-tabstops/ https://nick-gravgaard.com/elastic-tabstops/
- Zecc 6mo agoElastic tabspots everywhere would be ideal. But in the real world I think 'tabs to indent, spaces to align' is the superior way, as every dumb text editor will support it.
- Imustaskforhelp 6mo agoI have only read the first end of the article but I can't help but think that a project like libriscv[0] would've/could've worked for their game project too because fun fact but the creator of librsicv, the legendary fwsgonzo is also making a game. I highly recommend for people to check out their discord server. But my main point is that libriscv is one of the fastest libriscv emulators and then something like C/C++/lua could've been used with sandboxing purposes for the purposes of the game then. Am I missing something? Although, making a programming language is one kind of its own projects and that's really cool as well :-D but I would also love to hear the author's opinion on libriscv as it feels like it ticks of all the boxes from my understanding [0]: https://github.com/libriscv/libriscv https://github.com/libriscv/libriscv
- Twey 6mo agoIn the same vein Wasm is also an option that might be more suited to this kind of thing thanks to the higher-level ABI (/components).
- deleted 6mo ago[deleted]
- virexene 6mo agothis project is pretty interesting, although i'm wondering how they're planning to address the "easy sandboxing" design goal in a compiled language with raw pointer arithmetic and clib interop... in that regard i think lua would have been a lot easier to sandbox, despite the author's concerns. (also, they might want to look into lua userdata, since that would address their concern about the overhead of converting between native and lua data structures. the language is designed to be embedded in C programs after all)
- unnouinceput 6mo agoMaking you own language is easy. Creating the library that will actually solve problems without forcing the developers to reinvent the wheel is the crux. There is a reason why C++ / Java / JavaScript etc are established, it's the already proven libraries around those languages that allows them to be so successful.
- gobdovan 6mo agoI had a similar surprise about how approachable PL is, but from going from 'the bottom up' instead from a normal language. I wrote a compiler toolchain and debugger that takes a Turing machine description plus input string and emits an encoded tape runnable by a Universal Turing Machine [0]. I had some prior PL experience, but never did an end-to-end compiler pipeline, at least not this low level. It started as a joke/experiment, but I couldn't believe how fast it pulled me into designing: - a small low-level ASM for building the UTM - an ABI for symbol widths and encoding grammar - an interpreter used as the behavioral oracle - raw TM transitions for each ASM instruction, generated by having an LLM iterate on candidate emissions and checked against the interpreter oracle - a CFG-style IR to fix the LLM mess once direct ASM -> TM emission became too hard to keep sane (LLM did a decent job actually, I don't think I would have done a much better job without the IR either) - a gdb-style debugger for raw transitions, ASM routines, and blocks - a trace visualizer - a bootstrapping experiment where an L1 UTM/input pair was itself run through an L2 UTM - optimisation experiments And every step came quite naturally and was easy to tie in with everything else. Each one was just the next local repair needed to make the previous layer tractable. [0] Repo: https://github.com/ouatu-ro/mtm https://github.com/ouatu-ro/mtm
- rramadass 6mo agoThis is quite unique and interesting; thanks for posting. Seems like there might be some overlap with Tom Stuart's excellent Understanding Computation book - https://computationbook.com/ https://computationbook.com/
- gobdovan 6mo agoThanks for the link, will take a look. Yes, I did the project because I went on a side-quest while working on an article about all the ways we know how to compute (so basically the same theme of understanding computation).
- ecto 6mo agoThere are many like it, but this one is mine https://loonlang.com https://loonlang.com
- nithinbekal 6mo agoI've been having a lot of fun building my own programming language [1]. Getting to the point where you can write programs in your own language was surprisingly easy. The language, Sapphire, is Ruby inspired, so the most interesting part is digging into the internals of the latter when I'm trying to figure out how something should work. [1] https://github.com/sapphire-project/sapphire https://github.com/sapphire-project/sapphire
- amelius 6mo agoMaking a programming language is easy if you just copy ideas already existing in other languages. Coming up with new ideas is hard. Especially since you have to test them in the real world.
- imtringued 6mo agoI'm disappointed how many people just try to go for one more tiny incremental improvement or just make a programming language that suits their "taste", where "taste" just means similar to the programming languages they're familiar with (6 months+). I just don't understand how someone can spend hundreds of hours building a programming language that is basically the same as any other, when they could have used a popular language for serious work and then try out a novel concept for their hobby language. There is BerryScript which could have been a subset of an existing programming language plus a runtime optimized for that subset. There is also toitlang. They add hot reloading for microprocessors, which is good but that isn't enough to justify an entirely new programming language.
- simonask 6mo agoA significant reason is to learn. I’ve written a few myself, and it taught me a lot about why the limitations exist in other languages, but also just how things actually work. It’s a great exercise, and I believe that every lifelong student of the art of programming should do it at one point or another. The only mistake is when you treat it as anything other than an exercise. See also: A zillion alternatives to JSON that exist.
- coldcode 6mo agoI wrote my own interpreted language about 25+ years ago to write online surveys. It made it easy to create complex surveys with many branches. I think I wrote it in Objective-C. The team implementing the survey system wound up using the same language to implement the runtime portion, something I never expected or designed in. I don't recall anything about what it looked like now. I do remember it was a lot of fun to write.
- Tomokisan 6mo agoI watched a lot of youtube videos explaining in detail how to do it but i admit i never tried myself. I'm kind of curious and want to try it for fun as long as i get some free time ^^
- chrisaycock 6mo agoYes, it's true that someone can put together a simple language like in a university course. The difficulties, as mentioned at the bottom of the post, are things like metaprogramming features or optimizing compilers. The tail ends of a language implementation (parsing and code generation) are a fixed cost; the "middle end" can grow unbounded as more production-quality items are added. My language: https://www.empirical-soft.com https://www.empirical-soft.com
- atan2 6mo agoThis URL was posted two days ago: https://news.ycombinator.com/item?id=48040422 https://news.ycombinator.com/item?id=48040422
- sieve 6mo agoAnyone trying to do this... the first thing you do is avoid lex/yacc/bison/antlr. You do not need all this ceremony. A recursive descent parser that uses Pratt parsing will work for a vast majority of cases. The lexer/parser is never the bottleneck. In fact, you can write those two by hand over a single weekend for a largish language. With LLMs, it takes 15 minutes if you have an unambiguous spec. The biggest time sink, and the reason you will fail for sure, is the inability to restrict the scope of the project. You start with a limited feature set and produce the entire compiler/vm toolchain. Then you get greedy and fiddle with the type system, adding features that you have never used and probably never will. And now you have to change every single phase from start to end. I mostly give up at this stage.
- true_religion 6mo agoI wrote a few of these due to an interest in compilers and hardware. The easiest syntax to copy if you’re looking for a high level language is Smalltalk. But most of the time, I wouldn’t even use that. Simple imperative languages that look like BASIC works pretty well in most domains. If you simplify the syntax a little, it’s very easy to understand the compiler and use it for say when you want users to input code into existing systems.
- sieve 6mo agoI have written compilers for two families over the years: C and ML. My current preference is Python. I am currently working on a statically typed language that is inspired by Python (minus objects and OOP) that runs on a register VM. Syntax is a minor issue but something that people are very opinionated about. You could technically build multiple front ends that share the typechecking, CFG validation, optimization, register allocation and byte code emission phases. But it is too much work for what is presently a personal project.
- FattiMei 6mo agoAre they public? Can we study from them? Got later into compilers and I'm trying a little bit of everything
- sheepscreek 6mo agoEasier than you think to get started, but harder than you think to turn into something truly usable that isn’t a toy of an experiment.
- Decabytes 6mo agoLike most things in programming, handling the easy stuff is easy, but it’s all the edge cases that kill you. I’m writing an IDE in flutter right now, and all of the defensive programming I have to do to handle the unhappy path, is where 50% of my code goes.
- zenogantner 6mo agoSo maybe we need programming languages that are really good/supportive at handling errors (while not introducing more of them)?
- wg0 6mo agoStrange to read that C++ can be someone's favorite programming language. Only thing that goes for C++ is that it has acceptable (not straightforward) C interop. I don't like C# and X++ because the language surface is huge but if you use a limited subset than needles to say, very useful and handy languages too.
- debugnik 6mo ago> X++ I was very deep into .NET until recently but somehow I didn't know this existed. Looks like C# with extra Linq-to-SQL syntax; I guess it's a DSL made with Roslyn for ERP jobs? I wonder how they picked the name.
- SuperV1234 6mo ago> Only thing that goes for C++ [...] Nah, that's far from the only thing.
- ozgrakkurt 6mo agoThe compilers you get for both c++ and c are the best of any compiler. Clang is better than anything I have used in terms of the amount of options and features it has and also how polished it is
- Razengan 6mo agoFor years I've been fantasizing about a language designed specifically for gameplay development that doesn't try to be like C. Maybe AI is good enough now to help me with that.. The last time I tried, Claude couldn't even help me build a syntax highlighter for a hypothetical language.
- zzo38computer 6mo agoAt least in my opinion, it might depend what kind of game. For example, there can be: card game, certain kind of puzzle games, Pokemon game, etc. There might also be consideration of such things like what portability you want, what sandboxing you will want, etc. (There are game engines that have their own programming language for those kind of game (and some of them are the ones I had made up too).)
- hyper_frog 6mo agoAny reasons for not using odin? It seems great for gamedev
- Panzerschrek 6mo agoOdin has no destructors. That's a fatal flaw.
- hyper_frog 6mo agowell neither does C or zig right? but zig and odin do offer defer, which should be good enough while maintaining simplicity right?
- Panzerschrek 6mo agodefer is not a proper replacement for destructors. One need to write it manually each time in each function where some cleanup is needed. It's easy to forget to do so or to do this in a wrong way. Destructors in the other hand are called automatically and all cleanup logic is written exactly once (within destructor body).
- cv5005 6mo ago>One need to write it manually each time in each function where some cleanup is needed. You can structure your code to not need cleanup in every function. The biggest problem with destructors is, how do you handle errors? close() can fail you know?
- Panzerschrek 6mo agoUsually destructors can't fail. But for rare cases like with close() you can write a helper function (static method) which destroys the given object and returns an error if has one.
- Panzerschrek 6mo agoJust making a better C with no real compiler (only JIT) is easy, I agree. It's much harder to make something innovative and mature. It requires years of development.
- Mikhail_Edoshin 6mo agoTo me the most interesting part of a notation is the underlying thing that actually runs the code. The virtual machine, if you will. There are many ways to do that but I don't know a good systematic overview. E. g. what is Forth, if we ignore the notation? What is Lisp? What is Pascal and how it is different from C?
- BSTRhino 6mo agoGreat write up!
- tikotus 6mo agoI've also made my own language for making games. It's a scheme with some tricks to make some gamdev specific aspects much nicer. Making it work was indeed not that hard, but making it good has taken its toll. Really happy with it currently!
- larrry 6mo agoWhat modifications did you make to help with gamedev?
- tikotus 6mo agoAsync stuff, vector math (vector value type) and special let-style forms for pushing/popping render states. For example, if I want a drop shadow, I can do (vfx/drop-shadow [settings] ...) and a drop shadow effect will be applied to what is rendered within that scope. Also GC that works well with game style allocations where most of the allocations are dropped every frame.
- crowdhailer 6mo agoI think more people having a crack at a language is a good thing. It demystifies a lot. For a long while I wanted the install guide for EYG (my language) to be a tutorial to write an interpreter in the language of your choice. I thought following the guide should take about a weekend and cover every feature in the language. For production you might want someone else's implementation, but for getting started what a great intro.
- rwan3617 6mo ago[dead]
- dismalaf 6mo agoNice article. I always think it'll be fun to write a programming language then inevitably stall because most of the things I want already exist or are gargantuan tasks. Whenever I think I want to make a statically typed procedural language, I inevitably end up with Odin. Odin is just so damn comfy I can't see another language in the same domain beating it. Functional languages, it's hard to top Haskell, since it basically has everything ever invented in it. Replacing C++: always seems like a good idea until you get into stuff like macros, templates, name mangling and compiler specific nonsense. So you either just build something that compiles TO C++ (and compiles slow AF) or give up. Scripting language: I just love Ruby too much. Mruby is great for scripting, Ruby is great for system tools/scripts, it's comfy and has everything you could ever want. Lisps: sounds fun, I like Lisp-y languages, but SBCL is just a marvel of engineering that's impossible to not use. Attempts at another (OSS) native Lisp runtime always seem to end up waaaaaay behind in performance. So a DSL on top of SBCL Common Lisp? Maybe... Recently I got into stuff like Terra lang (basically a Lua-DSL that compiles to C which you can metaprogram with Lua) and Coalton so maybe a meta-language is the way... Also came back to Common Lisp so maybe I'll do a Coalton-esque language (but with a different set of compromises, not as "functional") on top of CL... Lisp productivity is insane and SBCL performance is too if you poke and prod it just right...
- subarctic 6mo agoOdd, I see a few mentions of sanboxing and no mention of wasm
- deterministic 6mo agoDon't get me wrong. I highly recommend writing your own compiler for any language. It is fun and you learn a lot. However if you make your own programming language and want to post about it on HN, please add something new to the language that makes the language interesting. I don't think we need yet another look-mum-I-made-a-compiler-for-a-language-that-is-similar-to-N-other-languages-but-with-a-slightly-different-syntax-and-zero-libraries post on HN. Just saying.
- iv4122 6mo agoThis is a fantastic breakdown! It's rare to find a guide that makes "writing a compiler" sound like a fun weekend hobby instead of a descent into the ninth circle of hell. My favorite part of the dev cycle is definitely the "wait, why did I name it that?" phase. Great post!