Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: What do you want to see in a systems programming language?
9 points by rpnx on Nov 15, 2023 | hide | past | favorite | 22 comments
I am working on a new systems programming language, similar to C++ with syntax that somewhat resembles Go or LLVM in some ways. While it isnt quite ready (at least a month away from alpha release), I am curious what features are the most desired in a systems programming language. I'd like to get inspiration for new language features. Pain points with C++, Rust, C, Zig etc.. What you like, don't like, etc.


A quick and easy way to add peripherals.

That's more than just device-drivers, you have to work out a consistent interface between the 'system' and all of the peripherals, rather than looking at the individual interactions of the system with individual peripherals.

In a way, you need something like the UNIX concept of 'everything is a file'. (Only more so.)

My hobby is writing emulators for real machines from the past. Most of my effort is in emulating the peripherals interactions with the CPU and RAM.

I have recently been looking at minicomputers of the 1970s. They seem to have had the concept of the peripheral doing all the work, with the 'system' merely 'asking a limited number of code questions' and the system 'getting a limited number of answers' from the peripherals.


I'm not sure that that is much related to systems programming, that sounds like a pretty high level library feature.


I don't see it like that. I see it as the system having only one interface with all peripherals. Or conversely, all peripherals get treated exactly the same way.

Maybe something as simple as:

     "Are you ready to send me data?"
     "Send me data"    (Some predefined size of data, maybe an 8-bit byte, maybe a 32-bit word, but only one defined size of data.)
     
     "Are you ready to receive data?"
     "Receive this data."

That goes down into the bowels of the system, probably at the hardware level. And the architecture of the interface has to be part of the low-level system language otherwise it gets fragmented.

But then again, I'm not a systems programmer so what I'm looking for may not be possible.


The main distinction between systems languages (e.g. C, C++, Zig) and non-systems languages is that in a systems language you can interface directly with the OS/hardware or at least a very lightweight runtime. If you need to talk in a language other than what the hardware speaks, you would need a layer inbetween the programmer and the hardware. Systems programming languages are what we use to create abstractions for non-systems languages, in particular runtimes. E.g. Java's JVM is written in C/C++. A defining characteristic of a systems programming language is that 99% of the runtime could be written in said systems programming language (maybe with some assmebly in the last 1% for system calls). That isn't possible in Java for example, you can't have a garbage collector that needs a functional garbage collector to exectute. Systems languages compile directly to machine code, and have enough features that can be used to interface with drivers and hardware. Systems languages have a very close association between what you write and how the computer works under the hood. Deviating from that von neuman model to make it do whatever you want is possible, but then it's no longer a systems programming language.


There's quite a lot of details that go into something like that and it's often not possible for the code to know all of them. Languages will sometimes abstract similar things out (e.g. have a function call run on some other processor across a network/bus and get the results), but it's quite a high level feature.

Systems programmers tend to demand a lot of visibility into what, when and how every line of code executes instead of abstracting that behind the language runtime. For example, a systems programmer might care that the data being received is transferred over DMA with zero copy.

As for features, honestly getting placement new without pointer shenanigans would be nice. C, C++ and Rust all make that (somewhat niche) use case more verbose and obtuse than it strictly has to be.


That is an operating systems thing, not a language thing


I want documentation, especially block diagram be the first class citizen of a programming language, such that parsing the code will generate project visualizations that can help me understand the big picture.


I suppose you could produce documentation as a compilation byproduct. But I am not sure that is within the scope of a "programming language".


A same way to handle strings, or return a complex structure without having to preallocate a buffer to write into, etc.

Clear semantics for dealing with threads and multiple cores.

Static type checking


Sounds like C++11 onwards. I plan to include all of those features of course.


I forgot to say NO macros, those evil things need to go


Oh yeah I'm with you on that one for sure.


I will be in the minority here, but:

Native integration with Datalog.

Many times, I find myself working on a program and I realize that what I need is a database. But having a database, even sqlite3 or Berkely DB, would be an overkill. If I could just express my data and the relationships between them, then I would be able to query what I need in an efficient way.


I would love to see a systems programming language with classes which were usable on bare metal, like with c++ and unlike e.g. D or free pascal where a runtime is required.

Any homepage of your project @OP to check for the alpha?


I registered rylang.net, but I have not put anything there yet. I'll put something there when I get further along. Only just added destructors for now.


A debugger


i never heard the term “systems programming language” before. is that a FAANG invention?


It's had its current meaning at least since the 60s with IBM and PL/S. I wouldn't be surprised if it was regularly used even before that though.


i don’t understand why c++ and other languages are labeled that way.


Because you can do "systems programming" in them.

What is "systems programming"? Roughly, writing OSes and the programs that come with the OS - compilers, linkers, debuggers, databases, and so on. The distinction is between "systems" and "application" programming. Again, this is 1960s language.

These days, there is a FAANG take on this. If I understand correctly, Google thinks of their software infrastructure as "systems programming". That kind of tracks with the old definition if you think of the entire company network as "the machine", instead of thinking about only one computer.


I think the meaning and the boundary has changed over time, but one of the most consistent features/requirements for a systems programming language is "embedability":

- functions that are called from a different language, like how parts of NumPy are written in C

- code that runs in kernel space

- code that runs on tiny little devices that don't really have an OS at all

In theory almost any language can do those things, but for a variety of reasons in practice we only use a small set of languages to do them.


I think one common trait is that systems programming languages have pointers and manual memory management or ctor/dtor based memory management (as opposed to a garbage collector). Non-systems languages abstract away pointers with some kind of runtime.

Pointers cannot be escaped. They are how the computer actually works. Either you expose pointers to the user, and all the errors that can result, or you have an abstraction layer where the limited set of automatic transformations are known to be memory safe. Low level/systems languages operate at the pointer level, high level languages translate to pointers through a limited set of transformations that have been proven memory safe. Rust is a bit weird because it somehow figured out how to do manual memory management in a mostly safe way that didn't result in a huge amount of overhead. Basically Rust works like other systems programming languages that use pointers with the additional constraint that also you have to write "lifetimes" that formally prove to the compiler that your use of those pointers is safe. Think of it as writing C++ but also having to write a proof that your code is correct.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: