Hi Andrew- of course I've been following Zig. Thanks for your trailblazing efforts in the "C replacement" space.
It's true that symbols in 'false' preprocessor blocks will not be caught. Maybe it's best said "if the compiler will find the symbol when you compile, then the symbol renamer will find it when you rename". Which is definitely not true for most symbol renames I dare to attempt in C++ IDEs.
Ah- for BeefLang that's less of a problem since even unreachable code is typechecked (without code generation). But yeah your problem sounds very hard. I guess I don't fully understand why you would only want reachable functions to be listed in documentation...
There are nullables (like C# nullables), same syntax: "int? a = null;". There's also algebraic data types like Swift's enum. Quite a lot like Swift's enum, actually. See bottom example in enum section: https://www.beeflang.org/docs/language-guide/datatypes/#enum...
The most obvious choice would be async/await support - no specific plans yet, though.
The concurrency model is, like C++ or even C#: sequential consistency for data-race-free programs (SC-DRF). No green threads or anything crazy, no 'message passing', just normal system threads, normal locks, you control how you access memory yourself. You do synchronization just like you'd do in C/C++.
If you go the route of async/await support - I went through the arduous process of figuring this out for zig (for which I think our design goals are nearly identical), and went through a couple different iterations. I have experience with using LLVM's coroutines API and abandoning it to codegen them manually. Would be happy to have a brainstorming chat with you sometime if you're interested.
I would appreciate it if more languages had something like ucontext_t or byuu/co, because I don't enjoy tagging every call site with "await" whenever I change a method to do something that might consume some time (and every call site of those functions containing call sites too, and so on), and because I do enjoy being able to write code that uses speculative execution (like for time-travel netcode for a 2d fighting game) without manually converting all my imperative code to a state machine like a compiler should do.
I am a bit of a snob, maybe, but I've come to think one of the bare minimum features for any language is copyable coroutines.
There's a lot of overlap ideologically. One major difference is that I'm an IDE fan and Jonathan dislikes IDEs. That can really percolate through a language.
BeefLang had an IDE on day one, and I think it'll show. One of my goals was to show how good a good IDE experience can actually be to someone who is used to working in C/C++.
> One of my goals was to show how good a good IDE experience can actually be to someone who is used to working in C/C++.
I wonder what you find lacking in the current C++ experience. e.g. with the IDE I use (QtCreator), I can quickly refactor things across million-lines codebases, perform a decent set of more advanced refactors (https://doc.qt.io/qtcreator/creator-editor-refactoring.html), auto-generate boilerplate code, I get in-line hints, lints and warnings while I type all with clang-based auto-completion...
personally I think the best IDE in the world is Visual Studio for C#.
I think Rust has the _potential_ to be better, but it's years off and requires the rust community to change how they think.
I'm interested in the IDE due to the authors claims, but I don't really see him making this IDE better than VS + C#. If he can, that would be amazing though.
> I think Rust has the _potential_ to be better, but it's years off and requires the rust community to change how they think.
The said change already happened and Rust devs are currently refactoring in depth their compiler to make it IDE-friendly (taking a lot of inspiration from Roslyn). This is tons of work though and even if it's currently going well, it won't be there before next year.
Console support important. That being said, there's a question of what console support means. For a programming language, that generally just means the compiler needs to be capable of generating binaries for the given target processor. The issue of how to interact with the hardware itself and how to participate in the toolchain provided by the console vendor is much more difficult and is outside the scope of the language/compiler.
The ideal case is for an engine such to embrace Beef and work through those issues.
Chucklefish was an early(ish) adopter of Rust and tried to maintain an XBox/PS4/Switch toolchain but eventually abandoned it. Rust is probably a good example of a popular "alternative language" that may pave the way for BeefLang and others to work their way into those spaces.
Fellow dev here, I think you're wrong on this part:
> The issue of how to interact with the hardware itself and how to participate in the toolchain provided by the console vendor is much more difficult and is outside the scope of the language/compiler.
I've been looking for a language that would allow gradual transition from C++ for example. If you have a C++ SDK, you could still write your whole engine or just some modules in Beef.
I was speaking more about when you have to conform to Nintendo's Switch build system (whatever that looks like - NDA) and you can't control much of that.
If you do have more control then you're in a much better situation, but crossing language boundaries can still be tricky.
Generally you end up having to write "wrapper" code to make those language boundaries palatable. There are code generators like SWIG to handle those things, and some languages like Zig handle importing of c headers, but if the C++ library your trying to use is returning a std::shared_ptr then that's not going to be a very pleasant construct for you to attempt to work with in any language besides C++.
If you can split your code sections into simple and clean C-like interfaces then the job becomes much, much easier.
Thank you for working on this awesome project. One additional commentary I always make is that I wish Go and Rust had even a basic editor like the one Racket has: you can edit, and compile. You beat me to that suggestion so I'll keep an eye on your project.
Is there any possibility that you'll include some efforts towards doing back-end networking with this language as well? I could see multiplayer games needing servers after all.
Yes, this is right - there is what is essentially a fully-functional "garbage collector" but its only job is to detect leaks in debug builds. Well, it also is used for detecting illegal memory layout changes during hot code changes...
One may say "then why not just make the GC optional like D", but when you design a library you really need to either design it for a GC or for manual memory management. Even for the basic string type - if Beef was a GC'd language then String would be immutable, but it's not so String is mutable. Totally different designs.
There's a split between class and struct. Classes are reference types and have more 'features', and structs are a lot like C structs - you have complete control over their layout and allocation.
There's future plans to add more high-perf sugars like automating some SoA and AoSoA layouts, but you can do all that manually right now.
You should probably do some perf analysis to show how Beef performs vs C / C++ for game related tasks.
Also it would be awesome for you to make a few code samples / tutorials on how to get started with game development with Beef. I'm sure it would attract a lot of people to your language if you show some "proof" it is a nice language for gamedev!
There are some optional memory safeties, including real-time leak detection, but this language targets an audience who value performance over total memory safety.
For someone looking for a C replacement where memory safety is absolutely critical (ie- open server applications) then Rust may be a better fit.
Linear types (and affine types, as in Rust) only buy you some memory safety (preventing use-after-frees, and memory leaks although that's not really a safety issue).
The more important part of memory safety is preventing out-of-bounds accesses. Rust, Ada, and (it seems) Beef sacrifice performance for memory safety here by having runtime bounds checking. (Though there is not much performance cost to this and all of those have options to turn off runtime bounds checking anyway.)
The only performance-oriented language I'm aware of that is fully memory-safe at compile time is ATS‚ via a combination of linear types and dependent types, and using ATS is… cumbersome.
It's better to manually hoist the bound checks so that they happen before any critical loop. The compiler often can't do this because it has to preserve the partial effects of where the failed bounds check happens, but that's generally not what you really want; if anything, you'd rather fail fast.
leaks aren't unsafe though. Things like bounds checking and aliasing guarantees are like 90% of the memory safety issues you care about, and those can be performant.
It's true that symbols in 'false' preprocessor blocks will not be caught. Maybe it's best said "if the compiler will find the symbol when you compile, then the symbol renamer will find it when you rename". Which is definitely not true for most symbol renames I dare to attempt in C++ IDEs.