- 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 !