I noticed some not so old VM languages like Lua, NekoVM, and Potion written in C.
It looked like they were reimplementing many C++ features.
Is there a benefit to writing them in C rather than C++?
I noticed some not so old VM languages like Lua, NekoVM, and Potion written in C.
It looked like they were reimplementing many C++ features.
Is there a benefit to writing them in C rather than C++?
C++ is implemented in C. I suspect everyone was following the C++ approach.
Even though modern C++ compilers skip (or conceal) the explicit C++ to C translation as a discrete step, the C++ language has peculiarities that stem from the underlying C implementation.
Two examples.
Pointers in addition to references is entirely because of C. References are sufficient, and that's the way Java, Python and Ruby all work.
The classes are not first-class objects that exist at run-time because the class is only a way to define the attributes and method functions in the underlying C code. Class objects exist at run-time in Java, Python and Ruby, and can be manipulated.
People are used to C. I have to admit that I'm more likely to write C for my own projects, even though I've been writing C++ since cfront 1.0.
If you want complete control over things, C is a little easier.
It's much harder to be "good" at C++, and until one is good at it they will have a lot of bugs and problems. Now, especially when working on large projects with many people, the chance that one of them won't be good enough is much bigger, so coding the project in C is often less risky. There are also portability issues - C code is much easier to port across compilers than C++.
I know something about Lua.
Lua is written in pure ANSI Standard C and compiles on any ANSI platform with no errors and no warnings. Thus Lua runs on almost any platform in the world, including things like Canon PowerShot cameras. It's a lot harder to get C++ to run on weird little embedded platforms.
Lua is a high-performance VM, and because C cannot express method calls (which might be virtual or might not) and operator overloading, it is much easier to predict the performance of C code just by looking at the code. C++, especially with the template library, makes it a little too easy to burn resources without being aware of it. (A full implementation of Lua including not only VM but libraries fits in 145K of x86 object code. The whole language fits even in a tiny 256K cache, which you find at L2 on Intel i7 and L1 on older chips. Unless you really know what you're doing, it's much harder to write C++ that compiles to something this small.)
These are two good reasons to write a VM in C.
In many cases, code in C could be much faster than C++. For instance most of the functions in the stdio.c library are faster than iostream. scanf is faster than cin, printf is faster than cout etc.
and VMs demand high performance, so C code makes perfect sense, although the programs would most probably take longer to develop.
One obvious answer is interoperability. Any time language X has to call functions defined in language Y, you usually make sure that either X or Y is C (the language C, that is)
C++ doesn't define an ABI, so calling C++ code from another language is a bit tricky to do portably. But calling C code is almost trivial. That means that at least part of your VM is probably going to have to be written in C, and then why not be consistent and write the entire thing in C?
Another advantage of C is that it's simple. Everyone can read it, and there are plenty of programmers to help you write it. C++ is, for good and bad, much more of an experts language. You can do a lot of impressive things in C++, and it can save you a lot of work, but there are also fewer programmers who are really good at it.
It looked like they were reimplementing many C++ features.
Are you suggesting it's easier to implement polymorphism in C++ rather than C? I think you are greatly mistaken.
If you write a VM in C++, you wouldn't implement polymorphism in terms of C++'s polymorphism. You'd roll your own virtual table which maps function names to pointers, or something like that.
Lua also has many features that are very easy to implement in Lisp, so why doesn't it take that as a basis? The point is that C is little more than glorified assembler code with only a thin layer of abstraction. It is like a somewhat polished blank slate, on which you can build your higher level abstractions. C++ is such a building. Lua is a different building, and if it had to use C++ abstractions, it would have to bend its intent around the existing C++ structure. Starting from the blank slate instead gives you the freedom to build it like you want.
Just a side note, you should look into CLR (Rotor-incarnation) and Java sources and you will note it is far more C++-as-C rather than modern or good C++. So it has a parallel there and it is a side-effect of abstracting for toys and making it average-performance happy for the crowd in managed languages.
It also helps avoid pitfalls of naive C++ usage. Exceptions and all other sort of things (bits David at boost consulting kicked off and more while we build sequencers and audio sampling before he even had a job :) are an issue too..
Python integration is another matter, and has a messy history in boost for example.. But for primitive data types and interfaces/interop and machine abstraction, well it is quite clear nothing beats C. No compiler issues either, and it still bootstraps many things before you get to anything as influential as it is/was/will be.
Stepanov recognised this achievement when he nailed STL, and Bjarne nailed it with templates.. Those are the three things always worth thinking about, as you don't have a decent incarnation of them in popular managed languages, not to that expressivness and power. All of that more than 20 years later, which is remarkable and all still bootstrap via C/C++.. Legacy of goodness (but I'm not defending 'dark age' C code c1982-2000, just the idea, yuo can misuse anything ).