CoalNova

On Zig

March 10, 2023 | 3 Minute Read

  One of the larger changes to the project has been an entire switch performed from C++ to Zig. This was not a choice made lightly, or for little gain.

  C++ had begun giving me problems related the very nature of existing as a nearly 40-year old language. These began cropping up in terms of handling data structures, correct utilization of SIMD types without needing extraordinarily lengthy documentation manuals, and worst: debugging. Essentially each change could cause a massive problem, and hunting down what the problem specifically was, where it came from, and what about the code was causing the issue. Many of these problems were caused by, or exacerbated by, the complex file layout required to prevent circular dependancies. Attempting to migrate codebase to work on linux, so that I could continue development on an extremly cheap laptop, presented further problems not exposed by the Microsoft Visual Studio suite. Also: Make. I am appreciative for what C++ has taught me, but am not blind to newer systems that elected to directly confront those (and other) challenges.

 Zig offered a host of features, bells, and whistles. It has more strict typing to prevent possible goofiness in accidental implicit type casting. It offers error unions, as well as error handling so as to crash gracefully. Performance on Zig should be near on par with C/C++, and even greater in areas where the compiler can detect and utilize hardware instructions not implicitly offered by C/C++ compilers. As well, if I can correctly utilize allocators, I may be able to exceed performance in some areas. Zig offers a feature out of the box which is flatly the best in my opinion: native C compilation. Any C library can be brought in and used, without the requirement of weird, third party interfaces possibly ignoring needed library features. This is possibly the best thing that they could have done, it exposes the language to decades of already existing libraries to use and build upon.

 The process of transitioning to Zig has been very interesting. Every time I begin learning a new language some part of my brain ‘resets’ and I seem to forget how to think programatically. The syntax obviously has a ‘new’ness that I haven’t had any familiarity with in C#, Java, PHP, or C++. I still get caught with prefixing type during variable declaration. With Zig being so new, and with it regularly updating and changing so quickly, searching for implementation solutions results in odd answers. Often times stackoverflow and forum answers include references to “possible upcoming feature” that has been in language for quite some time since, but I kvetch.

“Do not use Zig for production,” said the frog.

triangle of gl happiness “Lol,” said the scorpion. “Lmao.”

 Through reimplementation I have found faults within the existing codebase that I have been able to resolve or replace. Though cleanliness/tidiness/consistancy is still an issue, layouts may be more organically placed. I am still not using Zig to its fullest potential. Many of my implementations utilize a naive style of thinking from back when I was still learning C#. I am still pitfalling on occasion, and have had to redo solutions out of forgetting pre-existing implementation or std library features.

 That being said, I feel like the current iteration of the engine is the most foundationally stable at this same point compared to the 0.0.1 or 0.0.2 demo engines. Moving forward, the engine’s stability and fault recovery should be far in excess of its predecessors. In implementing what was assumed safe or stable concepts, I have learned that I could have very easily gotten myself trapped in endianness, or type conversion hell. I am still going to be doing terribly cursed things with type coersion to the GPU driver, so no worries of me coming completely clean. All in all it should be a wild ride, and a much needed boost to project completeness.