Something safer is desperately needed for embedded firmware development. Lack of such a language is already affecting physical safety of end user devices.
Something that can run for example on a microwave oven, car engine control, digital thermometer and industrial machinery.
Maybe I'm missing some, but some of the most important wish list items I can think of right away:
- High readability, Golang-like "understandability"
- Anywhere between 1 - 256 kB of RAM, 2 - 1024 kB of program ROM.
- Must have C-like code density and performance, but a small loss is acceptable in exchange for better safety.
- Ability to implement IRQ service routines, etc. low level code.
- Array access, pointer and type safety.
- Debugging support... this is a tricky one.
- Migration assist from C code. Doesn't need to be perfect, just to assist where ever feasible.
- Would be very nice: Some language level support for duplicating and checking critical variables in memory. Like those for controlling servos etc. physical. To improve end user physical safety.
Targets should include at least, in order of importance:
- ARM thumb-2 (like Cortex M0)
- Altera NIOS 2 (must be possible to modify easily to target custom instructions)
- 8051
Various Atmel architectures, MIPS and OpenRISC would also be nice.
But I guess it comes down to LLVM support for those platforms.
Specifically, it's a very good C replacement as it compiles to C. So you can easily run it on all of those embedded architectures.
While I must admit that it leans towards using a GC for memory safety, you can disable it and use Nim as a more readable C easily. If you're brave you can attempt to use Nim's GC in embedded hardware too, it's very flexible.
If you want statically guaranteed memory safety then do check out Rust, I'm assuming you already have though and dismissed it for some reason.
> Specifically, it's a very good C replacement as it compiles to C. So you can easily run it on all of those embedded architectures.
Yes, this is indeed a huge plus for this application.
>If you're brave you can attempt to use Nim's GC in embedded hardware too, it's very flexible.
I'm not going to be that brave. :)
> If you want statically guaranteed memory safety then do check out Rust, I'm assuming you already have though and dismissed it for some reason.
Static guarantees are good, less code and checking at runtime. I haven't dismissed Rust in any way. One huge bonus point for Rust is that it has a major organization, Mozilla, behind it. Of course, the fact that Mozilla is primarily interested to develop a web browser can be a liability. In the future, Rust might take a path that's less suitable for embedded firmware.
a actor model like language for the xcore mcu. supports actors(paralell tasks with communication chnnels, pattern matching on "events", assigning actors to diffeent "cores"-hw threads, boundary checks on arrays, special pointers(aliased/restricted) with good error messages, type checking, mostly compatible with c(except pointers)
Debugging is very good: Regular debugger, xScope - a virtual scope/logic-analyzer with access to internal states.XTA Timing analyzer - can determine(i think statically) the worse case timing between any 2 points in code. xScope and XTA might also work in simulation mode.
This complements well with their architecture ,which basically allows real-time without jitter, and with very high accuracy/speed, through usage of multiple virtual cores.
Very well fitted to industrial environment, and maybe they would be willing to add your request for memory duplication of variables , because it fits their niche.
"Ark is not a garbage collected language, therefore when you allocate memory, you must free it after you are no longer using it. We felt that, as unsafe as it is to rely on the user to manage the memory being allocated, performance takes a higher precedence. Although garbage collection makes things fool-proof and removes a significant amount of workload from the user, it inhibits the performance we were going for."
https://github.com/ark-lang/ark-docs/blob/master/REFERENCE.m...
This is the usual false dichotomy that languages subscribe to, where they presume that manual and unsafe memory management is the only alternative to dynamic and safe memory management. But Rust's secret sauce is that memory management is static and safe, thanks to linear types and the borrow checker. Rust is still the only competitor in the space of zero-overhead memory-safe languages.
Unfortunately, it has lots of warts that have sent me crawling back to C++. Addressing the particular item you're talking about here, manually specifying lifetimes of objects is a cure that's worse than the disease. It's great when the compiler infers everything for you, but I'm never going to be able to explain the syntax or semantics of those ugly 'a marks to my coworkers who aren't interested in programming language theory.
Anyways, I've been tempted to write a full blog post listing all of my Rust complaints, but I figured it's better to just quietly let you guys enjoy your thing. However, whenever I see these advocacy posts from you and the other Rust honchos, I can't help but scream a little bit inside. It's really not as good as it could've been.
To be really specific: it's great that you got "zero-overhead memory-safety", but I can't even implement fundamental data structures without using unsafe blocks and lifetime annotations.
But some GC schemes could be fast enough even from an IRQ handler, if memory allocation is just something simple like an atomic add to top of heap pointer. As long as non-interrupt level routines, potentially running on an another core, have enough time to clean up the garbage.
Manual memory management seems to be at the end of its road when it comes to high core count systems, with tens or hundreds of CPU cores. Allocation and application side object lifetime synchronization and management will simply saturate any inter-core communication mechanism, limiting scalability. GC should be able to get around that limitation. At that scale, you could already dedicate one or more cores just for cleaning garbage.
the only mainstream competitor, perhaps; ATS does a good job of it too [http://www.ats-lang.org/]
func main(): int {
mut i := 0;
for i < 5 {
printf("i: %d\n", i);
i = i + 1;
}
return 0;
}
I'm really curious about 2 things: that for seems to really be a while. Why := in the declare and = in the assignment?In fact, this snippet is only a few deviations away from being valid Go code.
foo := 3
fooo = 4
The second line is invalid because fooo does not exist.I chose `:=` and `=` mostly because of personal preference.
That is an instant red flag for me.
The fact that it's a year old is because the language has changed loads in the past, since I considered it a side-project that I would just play around with. However, after I stuck to something, it gained a bit more popularity and people started to help me out with it. Now we have ported to Go, with a decent sized team working on it (when we can).
It is impressive if you are only 17! Keep it up.
Keep up the good work, I can't wait with what you'll come up with later!
Goes to write some more bug prone C-based device driver code...
Still, because of tooling, direct C++ interop and familiarity we would have stuck with C++. The killer feature that elevates Rust above everything else - and made us switch - is the borrow checker.
But they still kept = for assignent and the very ugly == for comparaison. Into the trash it goes.