Juice also flows naturally from Franz PhD thesis, which was on JIT compilation of Oberon from what in some sense was a compressed serialized reduced form of the AST instead of bytecode [I'll stress this is a gross oversimplification - his compiler does do more processing, so I guess what is serialized is closer to an IR in tree form than the AST]. I don't know how much that changed in Juice, as I've never looked at it much but from the description it remains at least similar in concept. I've wished more work had gone into that ever since I read his PhD thesis in '94.
When compiling you had the option to generate proper native binaries, or slim ones to be JITed on load.
You seem to know a lot about this time. Would you have a reference on this report ? I am quite curious now !
(I use a similar mechanism of propagating vtables updates down the class hierarchy, but without the extra indirection - at cost of more memory - in my prototype Ruby compiler)
[0]: https://www.research-collection.ethz.ch/bitstream/handle/20....
I was a big Oberon fan[0], not so much for Go, because in mid-90's using Native Oberon was an eye opening experience, in the hardware we had available back then.
20 years later (at Go 1.0 time), not so much.
[0] - The whole linage, and still think Active Oberon is the best dialect (with AOS) that eventually came to be, after Oberon v1.0 from 1987.
As strange as it may sound, UNIX folks were Oberon fans, hence why ACME in Plan 9 had a similar developer workflow as the whole Oberon UI, where clickable text is combined with dynamic UI actions.
Plan 9 failed short of using a userspace systems language as C's successor (see Alef[0]).
Plan 9's sucessor, Inferno, fixed this with Limbo [1], where C is only used for the kernel, disVM, and a couple of userspace libraries, everything else done in Limbo.
Go ends up being a mix of Limbo, Oberon-2 method syntax and SYSTEM package.
However one thing that both Limbo and Oberon based systems have, and Go misses out, in how the whole platform embraces dynamic linking to extend existing applications, and surface operations to the UI.
By the way, I advise wasting a couple of hours diving into Inferno and Limbo's manuals[2],
[0] - https://en.wikipedia.org/wiki/Alef_(programming_language)
Also the abstract class thing didn't stop C++, lol
The thing that made Java great were conventions (file per class etc) and its standard library (esp collections)
Unsurprisingly, that is exactly what made Ruby great
really interesting that you work with something as niche as Oberon! :)
Can you talk about who is using Oberon, for what, and why?
Cool product, terrible boomer management.
Nowadays Oberon microsystems business has nothing to do with Oberon.
Have a look at this version of Oberon which has generic modules, exceptions, enumerations and much more: https://oberon-lang.github.io/
Also a concurrency concept is work in progress: https://github.com/oberon-lang/oberon-lang.github.io/blob/ma...
The potential was there, but in reality people just used Flash, and when the DOM/JavaScript interface became more competent, they switched to using JS.
And, yeah, as others pointed out... Java did not have generics, or enums until 1.4, and its exception mechanism hasn't really stood the test of time.
Also the way modern languages that are worshiped for forcing to handle return values, with pattern matching, try and ? operators, it is nothing other than proving the point checked exceptions matter, even if they come with a different flavour.
But it was the 2010s.
These days I work in languages with better static guarantees. Always wanted that back then, but felt like a minority.
But there's no guarantee that someone under you didn't go and pull out a RuntimeException on you.
- No generic types. That's really limiting. You want to implement Linear Algebra for vectors ? You need a class for each possible types.
- No proper error handling : no such thing as `TRY` or `CATCH`. Instead, you need to pass a `BOOLEAN` mutable flag in functions that may crash. That's just sad.
- No distinction between a class, an abstract class and interfaces / pure abstract classes. If you want to write an abstract class, you just `HALT` in the base methods (like you would do in Python I guess). But there is no language semantic to define that this class is abstract. So the compiler can't help you out much with them.
- No enumerations. They are just very powerful.
(- Faulty garbage collector, even though that is not a a feature of the language but rather of the implementation that I am using.)
I am quite sure that Oberon was written with a real focus on designing a language for which it is easy to write a compiler / garbage collector. It really made sense back then. And they succeeded in doing so. However, for broad distribution of executable, it probably wasn't the best guess. These glimpses of the past are so interesting though, discovery of the most optimal tech stack was a long and dense path of exploration !