I can't wait when it will be more mature. It uses QBE compiler backend [0] - "a pure C embeddable backend that provides 70% of the performance of advanced compilers in 10% of the code". Which by itself is very interesting. It does however only support x86_64, but it seems that work on arm64 is underway.
I like that it does not depend on GCC or LLVM. I also cheer Toybox, Oil shell and other rewrite-the-world projects - I'm that kind of weird.
It ticks many boxes for me. Rust brings memory safety, but I can't help the feeling that it just looks like C++. I wonder if it would be beneficial to implement a static analyzer for C, that would take into account additional ownership information on pointers. Something like:
#define OWN
int func(struct foo OWN*ptr)
So it would just compile to C, but the analyzer would know more.
Lately I'm wondering how good could be a dynamic language with a homegrown compiler backend. It probably does not have to be fully optimized to be faster than Python. Maybe it would not be as fast as Lua-JIT, but JIT brings it's own set of problems. It could be a fun project to make a compiler for Wren language for example. Such a language could target JVM and CLR as well.
Sorry for a brain dump, but I don't have time to make it more coherent. I may be too passionate about the topic, while lacking experience. I hope it is useful to somebody.
If I understand it correctly CheckedC woods as an extension to the language, so you need CheckedC compiler to actually use it.
I agree that SAL fits my description. Is it available outside of Windows? I've seen that someone wanted to add SAL support to clang [0], but decided against, because of Microsoft's patent on the thing [1]. Or than that it looks cool. Thanks for the pointer.
Looks very interesting from ergonomics point of view: it is indeed does introduce useful tools like generics, type inference, pattern matching, which are very painful to do in C. Though it seems like the language misses on popular nowadays generators, lambdas and coroutines. So I would say give it a plus on language design, and there is a space to grow.
Memory model looks C-ish, there are pro's and con's to it. Guess it works for the niche that language aims for.
What I think could be done better: compiler infrastructure / FFI. In this day and world interoperability with other languages is a must, and there is usually a need to provide standalone and embeddedable implementations of a language. IMHO would be great if Myrddin just compiled to C (like Chicken Scheme), that would broaden possibilities to use Myrddin as script language, or just use it side-by-side with C/C++. It can be done with the current Myrddin compiler implementation, but overhead of maintaining whole separate compiler/toolchain might be too big to enable wider adoption.
---
Edit: I was wrong, all functions are lambdas! Which is really great.
> Though it seems like the language misses on popular nowadays generators, lambdas and coroutines. So I would say give it a plus on language design, and there is a space to grow.
Lambdas are actually the only way to define functions.
const f = {args
/* do stuff */
}
is just assigning a lambda literal to 'f'. You can also just pass them around, if you want:
use std
const main = {
var value = 42
thread.spawn({; std.put("hi from a thread. I captured {}", value)})
}
Coroutines are possible to implement as a library, and generators don't fit well -- there are iterators, though:
use iter
const main = {
var v = [1,2,3,4]
for p : iter.byperm(v[:], std.numcmp)
/* use permutation p */
;;
}
> What I think could be done better: compiler infrastructure / FFI.
You can already link to C, but writing the function definitons function definitions are painful. There's ongoing work to take Andrew Chambers' C compiler implementation, and extend it so that it can automatically generate the glue code.
We had a Summer of Cod[1] person working on it, but they dropped out due to lack of time.
> Lambdas are actually the only way to define functions.
Oh, missed lambdas, that's great!
> You can already link to C
I mean, only on Nix-es, only in Sys-V-like ABI. What if I'm under Windows? What if it's not Sys-V? What if I want Javascript (aka emscripten)?
My use case is game development, I could have a need to ship to wide variety of platforms (for some you don't even have publicly available specs, like PS3), and this platforms only provide C/C++ compilers. Why Myrddin compiler take a burden of supporting all C ABI's out there by implementing it's own asm code generation? Easier way out code be just generating higher level code like C or LLVM IR, and using libffi to implement FFI.
I would love languages like Myrddin to succeed, but let's be pragmatic, it is nearly impossible to support asm code generation with all C ABI's without having a full time team working on it. It is a huge time investment (not even speaking of financial investment connected to it). So I find it's hard for languages to get traction because they keep getting stuck inside Sys-V/Windows realm :( While something that compiles to C somehow magically just-work on everything, even web.
Oh, also, you can abuse closures to do generator-like things with captures, thanks to the way they're implemented.
use std
const mkincrement = {inc
var x = 0
/* No GC, so the upwards closures are explicit */
-> std.fndup({
x += inc
-> x
})
}
const main = {
var g = mkincrement(5)
std.put("{}\n", g())
std.put("{}\n", g())
std.put("{}\n", g())
std.put("{}\n", g())
std.fnfree(g)
}
Will output:
5
10
15
20
The trick is that the function state needs to be in the capture.
> Lambdas are actually the only way to define functions.
How does that work with regards to interacting with the function? If you see that function in a debugger or print it out, do you get just a generic "lambda" name or does it do some magic to get "f" when defined and assigned straight to a name?
> How does that work with regards to interacting with the function? If you see that function in a debugger or print it out, do you get just a generic "lambda" name or does it do some magic to get "f" when defined and assigned straight to a name?
It does some magic to get `f` when assigned straight to a name. The magic is pretty trivial.
I think lack of objects/destructors is also a bit of a minus. Manual memory management is hard to get right, and if you're not going to go the Rust route, I think a modern systems language should at least provide RAII-style facilities for managing complex data structures.
Is defer commonly used for memory management in Zig? I'm not very familiar with Zig, but it seems pretty onerous to have to write defer { free(mything); } after every allocation that's supposed to be scoped.
I don't think it's valid comparison to Go, since that's a garbage collected language.
I just got through evaluating Zig. It's idiomatic to use defer right now but the language is also still pre-1.0 and making big changes, and that's one that might be covered in syntactical sugar at some point. Rust had a GC at one time, after all.
Overall Zig feels closer in intent to C than most "better C" languages. In its current form it has a lot of attention to detail about its behavior around common edge cases. It cares about not blowing the stack and dealing with OOM, and the default behavior of numeric overflow is a crash. Stuff that allocates to the heap is stuff that the programmer is made aware of, and "defer" is one of those little additions. It's less developed w/r to higher level abstractions, with the exception of a strong metaprogramming facility and sum types.
I've written less than 200 lines of Zig but have been kind of following its development on and off. My impression is yes, defer (and errdefer) are intended to be used for this purpose. I don't see the problem with it though.
The form "Merlin" first appears (as Merlinus) in Geoffrey of Monmouth's History of the Kings of Britain, c. 1136. One suggested reason why Geoffrey didn't latinise the Welsh name more directly as Merdinus is the unfortunate similarity of the latter to the French merde.
Nim has GC, looks like Python and compiles to C (or JS).
Myrddin has manual memory management, looks quite distinct (but I'm sure it borrows from many languages) and uses QBE as a compiler backend so it just produces binaries.
I can't wait when it will be more mature. It uses QBE compiler backend [0] - "a pure C embeddable backend that provides 70% of the performance of advanced compilers in 10% of the code". Which by itself is very interesting. It does however only support x86_64, but it seems that work on arm64 is underway.
I like that it does not depend on GCC or LLVM. I also cheer Toybox, Oil shell and other rewrite-the-world projects - I'm that kind of weird.
It ticks many boxes for me. Rust brings memory safety, but I can't help the feeling that it just looks like C++. I wonder if it would be beneficial to implement a static analyzer for C, that would take into account additional ownership information on pointers. Something like:
So it would just compile to C, but the analyzer would know more.Lately I'm wondering how good could be a dynamic language with a homegrown compiler backend. It probably does not have to be fully optimized to be faster than Python. Maybe it would not be as fast as Lua-JIT, but JIT brings it's own set of problems. It could be a fun project to make a compiler for Wren language for example. Such a language could target JVM and CLR as well.
Sorry for a brain dump, but I don't have time to make it more coherent. I may be too passionate about the topic, while lacking experience. I hope it is useful to somebody.
[0] https://c9x.me/compile/