Message board for the users of flat assembler.
> Programming Language Design > Starting to write a programming language
porky11 12 Feb 2019, 14:13
For some time I think about writing a programming language.
There are a few thing I like the language to behave.
The language nearest to my ideas is scopes, but it's still in development and also has a few concepts, I don't fully like. (In the end I'm probably going to use scopes anyway, but for now I want to try to make my own thing, so I don't have to wait for it and hope, it will really become good)
Some other languages, I got inspired by, are Rust, Common Lisp, which I both used a lot, c++ (which I had to use, but don't often use privately), and recently Odin (which I didn't really use yet).
There are a few general ideas I have in mind. I'm not exactly sure, what it's going to be.
A few general things:
It's compiled, has no GC, is statically typed (but it's possible to implement dynamic types in an expressive enough statically typed language, so this distinction is stupid anyway), every expression can be written at any level (functions, expressions), there exist a bunch of compile time evaluation features (generics, templates, macros, read-macros), everything is an expression and can return a value (no explicit return required), almost everything can be assigned to a name (similar to scopes, for example define the new name "outer-break" as "break" to break the outer loop from the inner loop), there's no main function (like in most scripting languages), and by defualt the program is executed, not compiled.
First the language will be parsed into s-expressions, basically lists of tokens. A token is either a symbol represented by a string or a list of tokens. It should be possible to add custom parsing behaviour similar to reader macros in common lisp, or rewrite the compiler as a whole.
I already implemented some modifiable s-expression parser in rust here.
There should be a parser, which uses indentation based syntax, like scopes, not sure if by default. This is at least useful for multi line strings and comments.
Then the s-expressions will be expanded. New expansions can be defined by the user at compile time.
The first token in the list specifies, how the form is expanded.
After the expansion, every list of tokens is required to start with a symbol and only a few symbols are allowed.
Then these simplified expresisons will be converted to some kind of syntax tree, which almost directly maps to some low level language, it compiles to.
Preferably, this low level language is simple and supports jit, like llvm and cranelift. C, Rust and wasm or other languages without garbage collector are also possible tragets.
I would like to use Rust to write the program, since I like it and using rust enums to represent the syntax seems to be a good idea.
The compiliation process already allows to implement most of the possibly wanted features, mainly inspired by common lisp.
But some other features are really important.
First there should be a simple way to implement generic structures, similar to c++ templates. Odin has a nice mechanism for it, but does only allow a few different types to be instantiated at compile time.
Scopes on the other hand has good compile time features, but no simple way to create generic structs (should be doable in scopes, too, as a simple macro).
The generic structs, I really want to have in a langauge, is a generic geometric algebra multivector type, which I was already able to implement in scopes (won't work in the next version anymore) and which also exists in a c++ library called versor, both not perfect.
Geometric algebra with compile time optimizations can replace a bunch of mathematical types with a single generic implementation: Vectors, Complex numbers, quaternions, double quaternions, and more.
What advanced stuff else I like to write libs for:
Some kind of ECS with compile time optimizations.
Some geometric algebra based physics library.
I also like how `using` works in Odin.
Most of the features from other languages, I like to have, are basically rust.
The borrow checker is nice to have, but it may be enough to have a workaround using `defer` or a system like C++.
There should also be orphan rules, but implemented differently:
There is an owning use of a crate, which allows implementing methods, the crate doesn't implement itself, if both types are from foreign owned crates, so it's possible to write glue crates.
The trait system in rust is also pretty nice, and scopes doesn't have something like that.
I prefer, that it's not required to define new traits, just to implement a method. Instead, there should just be methods, possibly defined in namespaces, which may have to be defined.
I would even prefer, if there are no methods at all, and there's a way to check, if a specific function is defined.
So instead of traits, only functions are checked and it's possible to define functions, which depend on implemented functions, which should be enough to declare types.
There might be simplifications to state, if a function is implemented.
So now a few new features, inspired by natural language, I came up with myself.
Function and type arguments should be referenced by type, not by name.
Varaibles should be able to be referenced using the type of the most recently used value.
Functions don't have to specify argument types nor return types. Both is inferred by the body when calling the function.
So this is a basic overview of what I want from a programming language.
If someone is interested in helping, or has tips, tell me please.
I know it's currently a bit vague, but I'm writing a more specific specification and may post it, too, when finished.
But before, I'd like to hear, what you think about these ideas and if maybe someone is already working on similar projects, I don't know yet.
|12 Feb 2019, 14:13||
donn 12 Feb 2019, 17:57
What don't you like about scopes? First time hearing about it, and skimmed through the doc and video, but SPIR-V was referenced several times and this greatly resonated with me.
The SPIR-V spec is available and combines the right amount of power and simplicity. Compute kernels can become too wasteful in their syntax in my opinion, but SPIR-V focuses, probably necessarily, on the essentials. scopes reflected some of this efficient simplicity at first glance.
I've been trying to remove a lot of what I see as waste by assembling SPIR-V in fasm and am learning a lot along the way. Reusing constructs, such as expressions or functions, can lead to interesting technical challenges. Haven't been using it lately, but ANTLR is one tool that can map out your grammar also, if you decide to write one.
Good luck with your project and its applications
|12 Feb 2019, 17:57||
porky11 12 Feb 2019, 18:16
There are just a few small things, I don't like at scopes, like the single inheritance of abstract types. Most other things, I don't like, are just low level ways, where are no convenient macros yet, or other things, that can easily fixed using macros. (that's why I think, I will stick to it anyway, when it's finished)
Maybe I should have another look at spir-v. I only know ir for llvm and cranelift. Maybe it's better to generate the spir-v first and find some way to compile this to machine code directly, which doesn't necessarily run on the gpu.
|12 Feb 2019, 18:16||
porky11 12 Feb 2019, 18:22
parsing is not the problem to me. As written, it already works in rust, and I just need to generate running code, so ANTLR doesn't help.
|12 Feb 2019, 18:22||
< Last Thread | Next Thread >
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.