I intend to take a more experimental direction with Zeta. It won't have an FFI, for instance. It will only provide a small set of minimalist APIs. The VM will be intentionally designed to avoid code rot and breaking changes.
Another thing I would like to experiment with is transparent compilation of pixel shaders to run on GPUs, the ability to run code in any language running on Zeta (given some restrictions) on both the CPU and GPU. I believe I have found a way to make this work, based on my type-specialization research.
Edit 16 minutes later: I just tried your benchmark with my VM-like language (https://github.com/akkartik/mu), and the time taken was almost identical. Interesting exercise! Here's the Mu and Plush/0 programs side by side:
$ cat fib.mu
def fib n:num -> result:num [
local-scope
load-ingredients
base-case?:bool <- lesser-or-equal n, 1
return-if base-case?, n
n <- subtract n, 1
fib-n-1:num <- fib n
n <- subtract n, 1
fib-n-2:num <- fib n
result <- add fib-n-1, fib-n-2
]
def main [
local-scope
x:num <- fib 29
$print x, 10/newline
]
$ cat benchmarks/fib29.pls
#language "lang/plush/0"
var fib = function (n)
{
if (n < 2)
return n;
return fib(n-1) + fib(n-2);
};
var r = fib(29);
print(r);JavaScript has massive bitrot issues. The HTML DOM is huge and constantly changing. I have had my own web apps break multiple times over the years. As for Python and C, if you stick to the core language, and minimize dependencies, you might be Ok. The problem is that the more dependencies you have, if any one of them break, they can render your program broken... And if you're not there to fix it, your program remains broken forever.
My argument for reducing API surface and keeping APIs low-level and minimalist is that the smaller an API, the more difficult it is to implement it wrong. It's easier for two implementations to implement a smaller API and have the same behavior. It's also easier to test small APIs for conformance, etc.
It seems to me that bitrot is fundamentally a result of change in the outside world. The only way to opt out of bitrot when the world changes rapidly seems to be to disengage from the world and become irrelevant. I'm fairly certain Mu will not suffer from bitrot in 30 years -- but it'll only be because nobody ever built anything with it :)
I can't prevent people from doing that. I can only put together the conditions to make it easy to write software that doesn't break, as much as possible.
> It seems to me that bitrot is fundamentally a result of change in the outside world.
Yes and no. On the one hand, some breakage is inevitable with changing conditions. On the other hand, the computers we have now provide the same basic facilities as computers did in 1969. It ought to be able to provide some stable building blocks, and hope that people will use them.
Currently, it seems to me that software breaks all the time, at a rate that is unacceptably high.
The surface area of POSIX is too high to build systems that can run for 10s or hundreds of years. Look at the design of Lua over Python. The assumptions it makes of the underlying platform are much much cleaner, thus it is more portable and easier to debug platform issues.
So when one uses Lua, it is up to the user to supply IO. This threading through the needle or hour-glass allows the users (embedder) to define how the scripts interact with the base system. This makes them more resilient over time, the interactions are better specified and highly mediated.
Somewhat analogous to the library vs framework dichotomy. Libraries survive better than frameworks do.
Can you point me at any Lua docs where I can read more about overriding IO in Lua?
I spent many hours fixing compile issues, memory problems that should have taken it down in the early 90's but didn't seem to matter at the time, and moving it to a modern socket API. I was quite surprised how much things had changed in 25 years.
How do you plan to do that?
The outside world will be accessible through a set of APIs that are small, have limited surface area. For instance, sound output will be done by writing raw samples. Graphics will be done with pixel shaders (functions which given coordinates return a pixel color). New APIs will be added over time, new versions of APIs will be added, but the older APIs will remain functional.
There will eventually be a package manager, and it will have immutable package versioning. That is, you can publish v5 of libtern, and I can depend on it. You can later publish v6 of libtern, but you can't change v5, so you can't break my code which depends on v5 when you publish new versions of your lib.
Obvious caveat: Zeta will have no FFI. You won't be able to immediately use all the libraries you could use in another system. I still think that building a huge amount of code that doesn't break could turn out to be a huge advantage. We won't try to satisfy every use case out there... But I think there are a lot of interesting and useful programs which don't need much more than basic keyboard and mouse input, audio and video output, network and file access (think photoshop, audio editing software, IDEs, etc). We will probably end up adding APIs for other things like MIDI, etc later on.
In the audio space, it is vital to support FFI for a plugin architecture because I can guarantee you your language isn't the-best-thing-since-sliced-bread for somebody who has stuff you really want available to you. Audio software lives and dies on the VST specification. (Audio Units are substitutable for VSTs--but the same problem remains.)
I admire your efforts, but perhaps you should understand the use cases of the things you want to use as examples before you try to employ them. It doesn't instill confidence.
2. We can build our own plugins
3. It's not impossible to translate or emulate existing VST plugins.
And yes, you can build your own plugins. You cannot replace the thousands upon thousands of VSTs out there. You aren't replacing, for example, RealStrat, which is a supersampled virtual instrument, without re-recording the entire thing (do you know how? Is anyone going to bother doing it when they can use existing, conventional software?) and simultaneously reverse-engineering the algorithms used internal to it. You aren't replacing even something comparatively simple like an Amplitube without heavy-hitting, lots-of-money algorithmic research in the first place. (And, on top of that, I sure wouldn't want to deal with the patent encumbrances!)
And pardon my skepticism, but emulating latency-sensitive, CPU-intensive stuff like audio processing strikes me as a pretty foolish idea. When milliseconds count, your emulation layer just gets in the way. What benefit are you bringing to make additional failure cases and additional latency worth a user's time?
You aren't reinventing the entire audio world; as with many other fields, the lingua franca is C and not you and no matter how much you yell at the mountain the mountain's not gonna move. If you want to play, you have to play with (good metaphor for music in general, now that I think about it). Maybe you should rethink some of your decisions, or better constrain your ambitions. Because right now--and this may sound harsh but I'm saying it because I like seeing people succeed--it sounds like you're doing the software engineer That Guy thing and handwaving away difficult things because they aren't conducive to the postulates you're starting with.
I'm also quite sure that an audio program with a plugin architecture will be feasible in Zeta, once it's more mature. The system is built for scripting, multi-language support and dynamically loading packages. It will be an excellent platform for plugins. You'll be able to define your own custom plugin language(s) easily, and then you'll be able to dynamically browse and load plugins from the package manager.
When you compare yourself to LLVM, you phrase the comparison as only an advantage (Zeta will be easier to use than LLVM), rather than a tradeoff (Zeta will aim for ease of use before performance, as opposed to LLVM).
I don't suggest that you start hedging your writing, but am just pointing out that if you make big comparisons, people will assume great ambition on your part.
As previously stated, my goal with Zeta is not to replace all existing VMs and to satisfy every use case. It's an experiment, it's an opinionated system. I'm going to do things differently from other implementations and try to demonstrate interesting things along the way. Even if Zeta never becomes popular, I know it will make people talk, and I hope it inspires other systems.
I'm not telling you not to have opinions, to be clear. I'm suggesting maybe you shouldn't adjust those pince-nez and pronounce so hard. Many systems exist the way they do for reasons that Software Developer That Guy cannot divine from outside; you just happened to hit on one that I know a little bit about.
(Photoshop is another example; professional-level tools require professional-level expansion. Because everybody's definition of "professional" is different.)
My own thoughts have been considering a wasm vm in kernel space. No need to ever exit kernel space; the wasm vm provides sufficient sandboxing. Wasm binaries could run on any architecture. Hopefully come up with a method that browsers can efficiently run wasm in directly in the kernel's sandboxing rather than having wasm-in-wasm. Syscalls could be exposed through wasm's import/export system. Kind of like that Metal idea in "The Birth & Death of JavaScript"
Another advantage that Zeta has is that it will come with useful building blocks for dynamic languages. With WASM, you have to implement your own dynamic typing, GC, JIT, etc, and the current WASM implementation doesn't yet support JITting.