You might appreciate appreciate Urbit's Nock, a "functional assembly language" based on combinator calculus which can be specified in ~40 lines of text, and implemented in ~100 lines of code:
https://urbit.org/docs/nock/definition/
As one might imagine, a naïve implementation of this spec would be extremely slow (for example, decrementing n requires incrementing another variable m in a loop until m+1==n, which is O(n)). A regular JIT can make even the braindead implementation decently fast, but in practice, specific implementations are recognized by the interpreter and replaced with faster ones. The benefit of this approach is that the code itself is rigorously specified by the combinator definition, and you can point the finger at the interpreter if the output from the optimized version differs from the naïve implementation.
Yeah, see that seems to go way too far, but then again this stood out as similar to ideas I've had:
> The algorithm for decrementing an atom is to count up to it, an O(n) operation. But if the interpreter knows it's running a decrement formula, it can use the CPU to decrement directly.
I had basically the same idea, only since my ideas still look a lot more like an instruction set it was in the form of explicit annotations to identify functions that could be replaced with a specialized instruction if available.
I'll have to look into this thing. Thanks.
You can go really, really far away from a computing system being a Turing machine with arithmetic, if you work at it - like, that's the thing you already have in every PL. But I think getting away from that also entails getting down and dirty with your chosen benchmark of expressiveness, and accepting that the system does not do some things well, and if you want to have multiple things coordinated, then you need to be careful about expressing that, too, to avoid just making a Turing tarpit.
Lately I've been thinking a lot along similar lines, but have come to a wildly different conclusion about how to do it. Of course, they are explicitly limiting their use-cases so that's to be expected. I generally agree with the idea of a VM that is simple to implement, but I think the result shouldn't look like real hardware with memory addresses and registers and a stack and all that, it should be more abstract and leave more implementation details up to the interpreter/jit.
Regardless, it makes me slightly less gloomy about the future of computing whenever I see more people coming to similar conclusions.