Titania Programming Language
Posted4 months agoActive3 months ago
github.comTechstoryHigh profile
calmpositive
Debate
40/100
Programming LanguagesCompiler DevelopmentWirthian Languages
Key topics
Programming Languages
Compiler Development
Wirthian Languages
The Titania programming language, a new language inspired by Oberon-07, is introduced on GitHub, sparking discussion about its design decisions and the motivation behind its creation.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
33m
Peak period
35
0-12h
Avg / period
9.6
Comment distribution67 data points
Loading chart...
Based on 67 loaded comments
Key moments
- 01Story posted
Sep 14, 2025 at 6:29 PM EDT
4 months ago
Step 01 - 02First comment
Sep 14, 2025 at 7:02 PM EDT
33m after posting
Step 02 - 03Peak activity
35 comments in 0-12h
Hottest window of the conversation
Step 03 - 04Latest activity
Sep 21, 2025 at 6:23 PM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45243925Type: storyLast synced: 11/20/2025, 2:30:18 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
> pointer_type = "^" type.
Instead of having println() or it’s equivalent in your programming language, add a new special character that denotes a newline after a string:
print(“Hello world”.)
I'm not sure of the value of seeing all of the variables used listed in one place, it has certainly led to me encountering a identifier scrolling up to determine the type then scrolling back down. When the variable is only used on a few consecutive lines it's just adding work to read and adding work to create. I daresay I have written harder to read code than I intended because I didn't want to go up and declare another variable for short term use. The temptation to inline the expression is always there, because you know what all the parts mean when you write it. It's only when you come back later that you get the regret.
It's possible it could be mitigated by defining something like (not sure if this is a valid grammar)
and bring in scoping on statement sequences. maybe call it stmt_block so that stmt_sequence can be a component that really is just a sequence of statements.Stop being overly dogmatic, it ALSO leads to worse code.
For example, search for "PROCEDURE Scan" here: https://people.inf.ethz.ch/wirth/ProjectOberon/Sources/Texts...
Control structures are deeply nested and this goes on for 64 (very dense) lines. The low line count but is an artifact of how Oberon is conventionally formatted. When reformatted to mimic the conventions of languages like C, Java or Python it works out to more than 120 lines.
When I program in Oberon (recreationally) I tend to follow this style even though I would extract the same code into a separate method were I writing in Java.
It means the compiler knows how much memory the function's activation frame will take and the offset into that for every variable before it encounters any code in the function.
Basically, it makes it easier to write a single-pass compiler. That was important in the 70s but is less important these days.
Does Titania not have/intend to have lexically local subscopes? That would seem very un-Wirthian to me.
I always thought there must be a better solution, like emitting the compiled function body first which just increments the offset whenever a space for a variable is required and emit the function entry after the function exit last, so you can set up the stack frame with full knowledge of it's use. Then the entry can jump to the body. Scoping to blocks would let you decrement the offset upon exiting the block which would result in less stack use which would almost always be more beneficial than the cost of the additional jump.
But this is not meant to be a fully fledged language, it's meant to be a teaching tool. If you want a fully fledged language that allows for out of order declarations, try Odin!
Also, the syntax of Oberon/Pascal doesn't really allow for it in a nice way. It kind of looks really weird when you allow for it out of order.
Variables are at the top because:
- you immediately see them (so, perhaps, easier to reason about a function? I dunno)
- the compiler is significantly simplified (all of Wirths' languages compile superfast and, if I'm not mistaken, all are single-pass compilers)
However, I feel that Wirth was overly dogmatic on his approaches. And "variables must always be at the top" is one of those.
Hint: This about this from a single pass compiler basis and how much memory needs to be reserved from the procedure's stack frame.
Are you sure you actually read my second bullet point?
If you read texts and papers by Wirth you'll see a single theme emerge: simplicity. Everything he didn't consider simple was thrown away and derided.
Unfortunately he got kinda stuck in that, and you can see it in all the Oberon flavors: he was clearly fighting against the limitations he imposed, but couldn't break out if them.
This made me smile; going to use it in the future.
Also, in true Wirth style, the documentation mainly consists of the language grammar :)
And I might plan on making this a recorded series of explaining how to make compilers from scratch with this language as a reference.
It's a bit more than just the grammar, but I agree it's generally underspecified.
Not trying to be confrontational, genuinely curious.. but why is this an area where you'd want a DSL?
My initial reaction is : When I'm learning a topic, the last thing I want to be worrying about is learning the ergonomics of a new language
I'm guessing there's a good rational I'm missing
it'd be nice to see some piece of compiler related code in this language that'd be ugly in a general purpose language
But the point of teaching compiler development is to teach people how to do the basic things from tokenizing, parsing, semantic checking, and code generation (directly to machine code).
I have found this is actually a skill most programmers don't even know how to do, especially just tokenizing and parsing, so I thought I'd use Oberon-07 as a base/inspiration for it.
n.b. at the time of this comment, the repo/project is not even 24 hours old yet.
Once students where proficient in Pascal, we could introduce compiler classes and, when sufficiently advanced, show what the Pascal BNF grammar looked like. So students had a complete picture of a language. Pascal's BNF grammar is very simple.
Also, Pascal enforces strong program structures (BEGIN, END, PROCEDURE, FUNCTION, etc). which helps to frame practical work.
> This is designed to be a language to teach compiler development with.
That is, this is the language a student would implement a compiler for. It's in line with what you'll find for most undergraduate compiler courses in terms of complexity.
Matz has Streem, SPJ is working on Epic's new language, the creator of Pony is working on MS' project Verona, probably lots of others. Doubt it will supplant Odin though, considering Odin's being used professionally.
Just wow....
If the latter, I wonder how you can manage another programming language alongside Odin — anyway, thank you and great respect for both!
If I get it right, Bill's language is considered for teaching purpose, which is also a goal of Wirth's languages, and for which these languages are well suited (especially for compiler courses). Also note that the name "Oberon" was not inspired by Shakespeare, but by the Voyager space probe's flyby and photography of Uranus's moons during the mid-1980s when the language was being developed (see https://people.inf.ethz.ch/wirth/ProjectOberon/PO.System.pdf page 12).
But I am using Oberon-07 as base, and I might deviate from it quite soon too. But I won't be going in the direction of things like Oberon+ (which adds generic and OOP programming) or Micron which adds the entire type system necessary to interact with foreign code. I just wanted something to explain to people how to do tokenizing, parsing, semantic checking (not just basic types), and machine code generation, and this seemed like the best language to choose.
n.b. I know the name does comes from from the Voyager space probe, but I wanted to keep it directly related somehow, and Titania was the best fit. It's also a moon of Uranus, and there is a story relation to Oberon (Fairy King).
And as I develop this, I'll tweak it more so that people can actually understand without having to know the full histories of Pascals or Oberons or whatever.
(Your grammar is missing a definition for proc_call, by the way.)
Also this isn't JS-style ASI technically speaking, and it won't have any of the problems either. The syntax for this language is different enough that it won't be a problem. Procedures don't even return things.
> Procedures don't even return things
Oberon allows return values from functions (which are still declared with the PROCEDURE keyword). It looks like the same is true in Titania:
<https://github.com/gingerBill/titania/blob/085b7b5bcf7f06076...>I'm curious what you're going to do with the code generator. Parsers are easy and can be completed in a day or two. Even with a reference implementation, however, it's the backend that's a slog.
As for code generation, direct machine code to a Windows AMD64 PE executable.
Backend should not be that difficult because I am not working on anything complex nor optimizing. This won't be an optimizing compiler backend course.
I would say it's probably not necessary to explain what the connection between Titania and Oberon is in the README. It's probably evident to most people?
I am curious about your thoughts on var parameters (i.e. mutable references), as in:
Rust also offers it, but you need to specify it on the call side as well.
It'd be nice to see some discussion of the motivation for its departures from Oberon07.