New language Carbon

Well… a struct is basically just a representation of a block of data and a class is basically a struct with extra level of visibility and a bunch of methods that allow you to associate your functions directly with an instance of the struct, so avoiding OOP is a bit like using a text editor (nano, for example) instead of an IDE for coding. Sure you can still write a program, but the text editor does little to make it pleasant. It also forces you to roll your own solutions to situations with known solutions using OOP library code and common OOP patterns, so you will get more convoluted code, more bugs and your dev time will be a lot longer. NIH syndrome is a real disease in programming circles.

You can do all this in rust with code tagged unsafe. Actually not sure about self modifying code but that is tricky in most operating systems anyway due to W^X. I dont know rust either, so cant speak with authority on it, but I recently started reading this https://docs.opentitan.org/doc/ug/rust_for_c/, which seems a nice intro to rust for a C programmer, and it is clear that you can use unsafe pointers and do unsafe arithmetic on them etc to your hearts content, and in an intuitive way (or at least as intuitively as in C), but without any of the safety guarantees that rust normally provides.

Again, I’ve got no practical experience of rust, but I notice some places where it is lower level than C, in a good way. For example, they don’t have an implementation defined, and inherently high level, generic int type, instead they force you to specify the width of every integer (like [u]intX_t in C) and you can even specify the width of literals. And they dont support implicit casting of one integer width to another, which is also forcing you tom work at a lower level than C.

Overall it appears similar to C in many ways but I get the impression they have thought about some of the nasty corners of C and sorted them out (or tried to). I assume it also has some of the disadvantages of C as well in terms of being slow to develop with (because its low level) and totally unsafe if you are using it to manipulate pointers unsafely etc. I’d also guess that it’s difficult to get rust to be as fast as C without turning off bounds checking all over the place etc, but that’s just a hunch. At any rate I’m enjoying reading about it. Next on my list to investigate is nim…

Lol so true.

1 Like

Re:OOP in Rust

What Java calls Interfaces are still supported in Rust so it’s not totally without OOP but pointer casting and aliasing are strictly disallowed in normal “safe mode” Rust. Classical inheritance requires those “unsafe” operations and adds hidden costs in the form of VTable lookups to what is otherwise a zero-cost abstraction normally supplied. Traits can supply those abstractions but they aren’t hidden in the function call syntax, it specifically makes you use dynamic dispatch only when you specifically ask for it.

Re: Foreign Function Interface

Calling C calling convention linker library or shared object code from Rust’s linker is perfectly allowed from “unsafe” mode and exporting unmangled symbols from C++ can be done as well. It just isn’t any safer to do so than calling inline Assembly.

Actually there are plenty of cases where Rust allows you to write safer equivalents of C without (runtime) overhead. Let’s take an example, suppose we’ve often going to need to store a number from 1-250, but it might not be set. In C we might decide to put this in its 8-bit unsigned integer, unsigned char (or uint8_t) and we’ll just remember that if this is zero, it means “not set” with 1-250 meaning obviously what they’d usually mean. We call this special use of zero a “sentinel” value. So in our code we need to check if it’s zero before just using it, because if it’s zero the value wasn’t set.

We can write Option<u8> in Rust meaning this is optionally Some unsigned 8-bit value, if it isn’t it’s None. But that’s going to have overhead compared to our C solution with a sentinel, this Option<u8> type is larger than the byte C used. However, Rust provides NonZeroU8, and the Guaranteed Niche Optimisation means Option<NonZeroU8> is the same size as u8 yet leaves our 1-250 (actually 1-255 would be permissible).

If you write code with this and compile it, you can see when you use it correctly (checking if there’s a value before doing stuff with the number from 1-250) the C and the Rust are producing equivalent machine code. Mechanically, that Option<NonZeroU8> is just a byte and the machine code for checking if it’s None just checks if it’s zero, like your C. Except, if you screw up in the C and forget to check for zero, you’ve introduced a silent bug in your program, if the Rust programmer makes the same mistake the compiler says this is an Option<NonZeroU8> if you need the integer you must de-structure it/ check it’s not None.

Rust’s type safety allows it to often deliver real safety benefits at no runtime cost. You’re paying for this at compile time of course, but buying faster computers for developers is much more practical than buying a new machine for every single user, or worse, putting a more expensive processor in your hardware product since the software is too slow/ big for the cheaper option.

1 Like

Self-modifying code is a bad idea not only because of operating systems, but also because processors with caches are not willing to execute it correctly.

On the early Pentium it worked but was extremely slow, because the processor would check for it and more or less disable its caches to make sure what you write (that goes in the data cache) is what you execute (that comes from the instruction cache).

Then there was probably some point where you could configure the caches so that it wouldn’t work at all (writes would go in the data cache, execution would be from instruction cache, no synchronization between the two).

Then now OS protect you against it with W^X. But you can still generate code and then later execute it (JIT compilation).

1 Like

i suspect the NN and MLAI will in the mid to near future replace a lot of programming tasks.

He’s not wrong, it is early days. I think that was a reasonable quote to avoid controversy.

If Carbon can do for C++ to what Zig has done with C, where tying in to C libraries doesn’t feel second class, it could be very useful. The reality is that billions of lines of code are in C and C++ and acting like they can all be rewritten in Rust or Zig or whatever is unrealistic. Maybe over the next 30 years, and the only way to get there is new, better languages which make it trivial to interact with the “older” languages.

I think for Haiku we will need to find a similar approach to API design for R2 and beyond and also attempts to add other languages as first class Haiku app implementation languages. Much like Apple has done with Swift.

2 Likes

Chandler Carruth knows LLVM and Clang very well. He is a good one to take on the challenge. I think he’s been part of the LLVM project since some very early days. The LLVM team has written in advanced C++ since the beginning, even before GCC allowed non C code in their source base. I hope Carbon imports old C++ source like Zig does to C sources and gives it some good streamlining in the process. If Bjourne Stroustrup is such a stick in the mud about immature code bases, his standards-making bodies could use some streamlining too.

Edit

After reading the article, it sounds like a sensible course of action.

Just an FYI, C++20 has added modules so maybe we won’t have to rewrite everything in another language after-all.

I personally don’t like C++ that much, so the thought of having other languages for Haiku is a good one for me. Though much of that could be that I am very behind and the only C++ I ever do these days is for Haiku, which is using a 20-year-old style. But I don’t get a good feeling about even modern C++ when I see people like Adrien complain about all the various footguns and things you have to work around and he uses it every day. How many “Effective C++” books do we have these days? Four I think…that says a lot.

Of course I use Go all day and can complain about various things about it so maybe that isn’t a great argument.

But I think even without liking or not liking C++, it won’t hurt Haiku to have alternative SDK languages if they can be integrated nicely.

3 Likes

I hope that API will be not redesigned from scratch and old apps will be still functional. I think that it is possible to make C++ ABI compatible interfaces and bindings with LLVM.

Swift is ABI compatible with Objective C, so it do not require full API libraries rewrite.

1 Like

Another thing that says a lot is how long it’s taking to get to R1 in the first place. Granted, it’s on limited staffing but it doesn’t catch bugs in the parser to let us box at a higher weight class like Rust.

I think the contrapositive. I hope the compatibility layer on top of whatever OS comes next is thin and allows an effective progression from Haiku to a next gen platform.

Hosted AROS is better than AmigaOS 4.1FE because AROS hosted runs like an App on the memory-protected Linux kernel while AmigaOS 4.x is dying on the vine because the API remained fixed on the PPC based ABI.

The only reason MorphOS is doing better than AmigaOS 4.1FE is that the old PowerMacs that it runs on kept a steady stream of usable hardware coming such that my G4 Mac Mini runs circles around my MicroA1 but costed much less.

In another case WINE has been helping people leave Windows behind. Linux having no fixed ABI has been helping people recompile open source to BSD-alikes as well, including Darwin.

There are loads of migration paths to look for.

1 Like

“Next gen platform” may hear good, but do Haiku team able to design such thing? There are almost zero success stories of noncommercial GUI framework designs. I worry that attempts of “next gen platform” design will spend a lot resources and give no result. It may also bring large controversy and result project to die.

I think that it is more constructive to identify missing features and extend existing Haiku API to support it. Be/Haiku API is not so bad that it can’t be extended without total redesign.

1 Like

My half-hearted support for C++ is falling on deaf ears so it seems inevitable that we will move to something else eventually. The sticking point is the browser engine. There are a few C++ ones available, no Carbon ones and rust-based Servo seems to have languished into irrelevance.

Well I don’t want you to think that it is inevitable that Haiku drops C++ (it certainly isn’t my call to make), in fact I think that is probably unlikely. I personally don’t love C++ as I have made clear, but I think the way it is used in Haiku is pretty decent, and I like the API design too.

I just think it would be nice if it wasn’t painful to use other languages to make Haiku apps. It doesn’t mean we rewrite everything, it just means that if some Rust or Zig or Nim developer wants to write an app for Haiku, it isn’t totally foreign or overly difficult. This is like a 10-year plan sort of thing, and something we can all experiment with on the side before the actual Haiku project chooses anything.

Maybe it involves an official and high-quality C-ABI wrapper (if possible, it might be overly difficult as PulkoMandy has implied before.) Maybe languages like Zig or Carbon can help. Maybe we find an innovative way to support the C++ ABI with other languages. If we are just talking making it work on Haiku alone, that might be more possible than people who want to do it across platforms.

Maybe we just make a new C ABI libbe that talks to app_server and shares the be_control_look code with the C++ version (so things look consistent), and then other languages can wrap that. I don’t know, there are a lot of options, people can play around.

Right now anyone could write the core business logic of an app in Rust, Zig or whatever is supported on Haiku and wrap it in a fairly simple Haiku C++ GUI interface. In fact I want to give that a try and prove it is viable sometime in the future, probably with Zig, depending on the state of our port.

The Genode devs just trimmed down C++ complexity to create their own dialect, that better suits their OS:

3 Likes

That’s precisely why I don’t want it to go on forever. What it’s mainly got going for it now is that it is a lightweight, efficient OS. Linux started out being a lightweight kernel with a quirky, open-source license. As it caught on, however, is it became bloated as more and more “features” were added to its monolithic kernel. Now Linux is bloatware such that Windows has almost caught up to it performance-wise. Size matters! If it doesn’t fit into the caches, it needs to be offloaded from the kernel into a library.

One kernel I’m looking at for the next generation is TheseusOS. It avoids the need for memory protection by using only safe Rust code in the kernel and using WebAsembly for the user-space add-ons. The only memory shielded by an MMU is unallocated space so less memory fragmentation happens in the flat memory model. It is currently only usable for embedded applications because of the lack of drivers but it will likely grow as Haiku also grows.

That is the lifecycle of operating systems. I used to like AmigaOS because it used to be lightweight and agile. Version 4 changed all that with its hardware requirements changing from a 68000 based machine with Amiga’s proprietary chipset to a PPC machine with PC peripheral cards. Bloat set in and now it’s barely worth using on QEmu, let alone new hardware.

P.S. Sorry about drifting off-topic.

1 Like

I already used this approach to port Oberon GUI framework to Haiku: GitHub - X547/BlackBox-Haiku: BlackBox Component Builder port to Haiku operating system. It directly produce C++ vtables, type_info etc. Some LLVM-based code generator can simplify interacting with C++ ABI.

1 Like

No, that is the lifecycle of bad designed operation systems. Windows first version was released in 1985 year and it is still most popular desktop OS and core GUI API are still the same as in Windows 1 (you can even recompile Windows 1 application for Windows 11).