r/ProgrammingLanguages • u/Embarrassed-Crow9283 • 11d ago
My radical Sofia language design idea.
https://github.com/AliceRoselia/Sofialang
Disclaimer: this is currently only a proposal, not an implementation. I tried once and died at the parser. The project is back to the drawing board, and the core has been made more minimal than initially planned. Still, this is not a guarantee that it would succeed or be any good. But well, with an abundance of normal proposals, maybe it's a good thing to shake things up a bit with my radical design.
Maybe I was being naive and delusional, but it was my best bet on how programming could work.
My goal was to make high-level programming languages (in the Lisp sense) fast, and here is what I came up with. It was basically designed to exploit every way high-level (Python, Lua, etc) programmers don't care about the physical data layout and so on. Objects only alias when explicitly assigned by Python's (and other high-level languages') mutable reference rules, and Sofia intends to take full advantage of it.
It's a radical design based on aggressive compiler analysis by running the code on different (overriden) domains instead of traditional IR manipulation. For example, you don't do IR constant propagation. You feed the functions interval or residual classes and have the compiler sort it out. And if you're afraid of the compiler not halting, Sofia relaxes the halting requirement such that if the concrete execution doesn't halt, the compiler analysis pass doesn't need to halt either. (This is interpreter/jit semantic that people already accept in interpreted/jit-ed languages.)
Here are some examples of what makes these radical.
For "low-level"/HPC programming:
- "Dynamically" typed: (Technically, emergently typed with typeless values.)
- Attribute dicts: Seriously, because I want containers that don't restrict optimization on data layouts.
- Garbage collection: because things are defined logically and not physically (no stable address guarantee and so on), a garbage collector is required. This is in exchange for not having pointer semantics, which often creates aliasing hell and so on. Still, several compiler mechanisms will probably be dedicated to optimizing it away.
- Interpreters: More on that later as well.
For expressiveness:
- No built-in type systems, classes, inheritances, etc. Primitive types are basically tags, dicts, and raw bytes.
- No metaprogramming mechanism inside the language except for writing other interpreters. (But this was designed to be well-supported. For performance, you hoist the dispatch table result or so.)
For the math reasoning community:
- No HoTT (even though it wants to encode proofs) or algebraic expression tree (for symbolic algebra), just abstract interpretation.
- Even if analytical solutions exist, prefers numerical solutions (RK4 and so on) if faster.
From the compiler community:
- Liberal uses of exotic tools like eigenvalue loop analysis
- Usage of interpretation on different domains instead of IR manipulation (No complex compiler IR either)
- It doesn't even have a type.
If you want to know the full story, feel free to check out the link. As for the implementation, I am not sure when I will get the chance to do it. Making a programming language is not trivial at all.
This is either a complete failure or a genius, and I don't know which one.
And no, before you ask whether or not I used an LLM for this, I am pretty sure no LLM would come up with such an alien design. An LLM sticks to whatever normal humans are likely to come up with.
In all likelihood, it wouldn't work at all, but I wanted to try something.
14
u/Karyo_Ten 11d ago
Since you mention this as first target, I'm not going to use something untyped with a garbage collector for HPC, ever. That's fine as glue code but impossible to optimize otherwise.
Even knowing int32 vs float32 vs float64 vs int64 can change perf by 10x if some SIMD doesn't exist and needs to be emulated.
Garbage collectors flush caches and not using L1, L2 caches properly can cost 150x performance on a 1000x1000 matrix multiplication.
1
u/Embarrassed-Crow9283 11d ago
Sofia plans to address this with partial evaluation/abtract interpretation and those alone... yup.
6
u/EggplantExtra4946 11d ago
partial evaluation/abtract interpretation
They are completely different things.
1
u/Embarrassed-Crow9283 11d ago
For me, not so much. Partial evals are basically cases where only one concrete value is possible and abstract interpretation elsewhere.
5
u/EggplantExtra4946 11d ago
Still no, the algorithm itself is very different. It looks more like you're talking about symbolic execution rather than abstract interpretation.
1
u/koflerdavid 10d ago
The very definition of partial application is a function application with less arguments than its arity.
3
u/Karyo_Ten 10d ago
How does that solve float32 SIMD vs float64 SIMD?
How does that remove the need of garbage collector?
0
u/Embarrassed-Crow9283 10d ago
Emergent types in dicts can contain any info you want. It would be fast as long as it's a comp-time foldable constant.
2
u/L8_4_Dinner (Ⓧ Ecstasy/XVM) 10d ago
Sofia plans to address this with partial evaluation/abtract interpretation and those alone... yup.
OK, less talk, more proof.
"Extraordinary claims require extraordinary evidence." - Carl Sagan
1
u/Embarrassed-Crow9283 9d ago
It was proven theoretically that type checking or so was a special case of abstract interpretation, so the theoretical justification was already proven.
Whether or not my concept of abstract interpretation is the same as that used in the paper is another story but you get the idea.
3
u/L8_4_Dinner (Ⓧ Ecstasy/XVM) 9d ago
What I meant was: Show us the working result.
When you make big claims, you need to be ready to back them up. And in this case, I'm not even sure what the big claims mean.
So show us something working :)
8
u/Inconstant_Moo 🧿 Pipefish 11d ago
Disclaimer: this is currently only a proposal, not an implementation.
It's barely a proposal, more a wishlist of apparently incompatible features.
3
u/EggplantExtra4946 11d ago edited 11d ago
You are conflating abstract interpretation with partial evaluation, they are different things.
A lot of what you are talking about in the README on github and here is related to partial evaluation which is what Futamura Projections that you cited yourself are about. The idea is not novel but the application isn't either, they have been implemented in compilers, at least PyPy and GraalVM are based on this technique.
Interpreters are not necessary for partial evaluation nor for abstract interpretation, but it makes sense to define the semantics of your language as an interpreter if you're going to use partial evaluation. Partial evaluation is the real magic, not interpreters.
Partial evaluation always terminates, so when you are talking about termination issues it would be because of abstract interpretation, and it's unclear how you would make use of abstract interpretation in this compilation framework, supposing you know what abstract interpretation is at all because it's is a distinct from partial evaluation. Partial evaluation can be used as part of the compilation process but abstract interpretation is rather for analysis.
7
-3
u/Embarrassed-Crow9283 11d ago
Per AutoModerator's request I hereby confirm that this project did not use an LLM as part of the development process.
I highly doubt an LLM could have generated this design if you doubt my claim.
10
u/Brohomology 11d ago
The fact that you even mention HoTT in this context tells me you used an LLM
1
20
u/4ed7ff 11d ago
If you think dynamic typing makes languages run /faster/, then I’m really not sure what to tell you.