Compulsory Michael Franz (author of the linked paper) fanboy-ing:
Prof Franz did his PhD under Niklaus Wirth. His thesis was on Semantic Dictionary Encoding - a method for storing a compact semantic tree representation of a program in what is effectively a prefix code (e.g. similar to Huffman coding) that it exploits beautifully to both compress the tree and to use heuristics (the same on the encoder and decoder) to generate templated code fragments to allow the code generator on load time to do less work. Published in '94, it unfortunately was totally overshadowed by Java.
It's still one of my favorite papers, and one day I still want to go down the route of actually implementing SDE properly (there are implementations for Oberon - one of the early remarkable feats was that because of the more compact representation, on MacOberon it was on some hardware faster to load and generate code from these "slim binaries" than it was to just load a native binary, because the code generator was fast enough to beat the disk IO cost of loading a larger binary...)
One of Franz' PhD students was Andreas Gal, who wrote the paper on trace trees and applied it to JIT'ing Javascript, and worked as CTO at Mozilla.
Unfortunately not yet. My compiler project has stagnated a bit, though I still work on it occasionally (most recently I've now come to the point where I have to implement GC - the compiler racks up 2GB of mostly garbage while trying to compile itself...). I do want to eventually retarget it to SDE, but it's unlikely to happen this year...
> MacOberon it was on some hardware faster to load and generate code from these "slim binaries" than it was to just load a native binary, because the code generator was fast enough to beat the disk IO cost of loading a larger binary...)
The CPU/Memory/Disk gap has only grown since then - even with SSD drives it is still a lot bigger than twenty years ago. So this is probably even more true today than back then, no?
Reminds me of blosc, which uses data compression algorithms that are so fast that the cost of spending CPU cycles on it is lower than the savings in terms of reduced time to read/write to disk[0].
It very well might be that gap has grown, though I think the expectations of optimizations of the code has grown too. On the other hand, we now have more cores than we know what to do with, so an interesting approach would be to start generating code, and inserting calls to the code generator for pieces that hasn't been generated yet, and farm out generation to multiple cores.
If the code is structured right, and you could certainly try to sort the code based on a dependency graph, you don't even need to load the entire file before you can start generating code from SDE (but you'd need to be prepared to stub out forward jumps so they point to something that'll generate or wait for generation of the rest where necessary).
Well, after quickly skimming through at the PDFs linked here, it looks like SDE are a good data structure for IR, and that one could compile one SDE into another.
So it looks like you could do some kind of heavy "portable optimisation" pass first, then distribute the resulting SDE of that, and do a second, lighter pass of "local" optimisations targeting the local architecture.
That's true. There's also always the option of treating SDE as an "installation format" rather than "runtime format" and generate optimized code for a given architecture at installation time. Optionally it opens the door for funky things such as generating code instrumented for profile guided optimization first, and in the background/offline continue to optimize the code.
(in fact, I believe quite a lot of Franz' subsequent research has been in areas like that, though mostly JVM focused)
Hm very interesting. But to play devil's advocate, what's wrong with the Java approach or the v8 approach? Is it just that they are suboptimal in terms of efficiency, or is there something that SDE can accomplish that they can't?
The Java approach is to do parsing, semantic analysis, and compilation to bytecode on one side of the network. Then JIT compilation is done on the other side.
The v8 / "modern JS" approach is to do gzip compression of source code on one side of the network. Then decompression, lazily parse, and lazily generate native code on the other side.
Now I recently look at v8's parser, and it's fiendishly complex [1] and somewhere north of 20K lines of code -- and yes that's just the parser.
So there are downsides. SDE might be more elegant and efficient overall (?) But when you are dealing with networked code, you can't change both sides of the wire at once. So we are sort of stuck with suboptimal interfaces and brute force on both sides.
That said, I do think there is a good argument to be made for shipping plain text source code and using brute force to make parsing and analysis in the browser fast. (That is, writing ridiculous amounts of hand-tuned C++ code.)
There's nothing "wrong" with the Java or V8 approach per se. It's not even a given that SDE would do better today. Note that most of Franz' own work has since been on the JVM.
I just think SDE is worth more exploration. It lost out not because it failed to compete on merits with the JVM but because the JVM basically cut short any hope of it getting mindshare at the time.
It's possible the JVM or V8 approaches are simply superior designs. But we don't really know, because such huge resources have gone into making the JVM or v8 approaches work, and not just SDE but most other approaches from that time became near instant dead ends.
> The v8 / "modern JS" approach is to do gzip compression of source code on one side of the network. Then decompression, lazily parse, and lazily generate native code on the other side.
The interesting part of this is that you could treat SDE simply as a way to short-circuit the parsing and compression step by using it to serialize the AST and still retain exactly the same code generation. You can lazily generate native code from it, as long as you apply the heuristics to build the dictionary on load time (necessary to rebuild the correct tree).
Whether it'd be worth it is an open question, but I wish I had time to explore it.
I'm actually exploring something "spiritually" related: currently, I have a project where I store the state of an app in the URL, by compressing trees of JavaScript objects by first putting them through a pre-compression "filter" step to make the data more compressible (not going into that now, but see [0]), then apply JSON.stringify, and finally put the resulting string through lz-string to create an URI-safe string[1]. lz-string is basically a wonderful, wonderful hack to Lempel-Ziv compress strings to a bitstream, which is then turned back into a string.
I'm basically looking at ways to cut out the JSON.stringify step. So basically, first turn a JSON-friendly object into a binary representation, which is then compressed into a bytestream, and stored in a URI-safe string.
This might lead to something generally usable, and faster/smaller than lz-string. I know JSON alternatives like flatpack and messagepack exist, but this would be a much simpler, lighter JS library, single-digit kilobytes in size before gzipping. It also would probably be backwards compatible all the way to IE6.
That's interesting. Yes, I'd encourage looking at how SDE functions there, as
SDE is ultimately using Lempel-Ziv-Welch that operates directly on a tree instead of a serialized string, and where the heuristics for what to add to the dictionary can include templated tree subsets.
That part of it is really independent of the code generation aspect, and could easily be adapted to serialize arbitrary types of tree structures.
Basically what you need is a general mechanism that takes a possibly templated rule, and adds to the dictionary. Then you need a mechanism that looks at a JS object and instead of spitting out JSON, matches the current node to one of the dictionary items and spits out a bit pattern and then recursively spits out the bit pattern for the template arguments. The decoder can basically be very simple recursive descent: Identify the dictionary entry, look it up, find the template rule, recursively call itself to retrieve the template patterns, and reconstitute the object.
The "magic" then lies in the heuristics, which can be very generic (e.g. suitable for any JSON) or very specific (e.g. embedding domain knowledge of what the trees are likely to be shaped like, or at least code to be able to recognize and encode complex shapes when seen).
It is lightly "compressed" -- there are no native pointers, but offsets instead. The in-memory format is the same as the on-disk format. You can mmap() a file and then start following "pointers" right away.
I didn't develop it for transmission over a network, but it could be used in place of Python's .pyc files, which essentially cache parsing and bytecode compilation, and are a big tree/graph data structure. It can represent arbitrary graphs.
You could add dictionary compression in a tree-aware way or a tree-oblivious way... not sure how that compares to SDE.
FWIW someone suggested WebAssembly on that thread, but it's apparently no longer an AST -- it's bytecode (I guess more similar to Java.)
That's interesting. I think where SDE goes further is that you can go full lzw with it. The "dictionary" here is not a static dict, but a dynamically built dictionary as with lzw compression that is expanded as you parse the stream.
That makes it harder to traverse - you can't jump to arbitrary locations without decoding everything before it, because you need to look at everything to apply the heuristics to build the dictionary. But it makes it likely to be far more compressed - e.g. you can have dictionary entries shorter than a byte, and you can build dictionary entries that represents whole subtrees, and in SDE's case those subtrees can be templated.
Hm, but if compression ratio is the only difference, then I don't see that as a bottleneck in most language systems?
I think that overall startup time for example is a more interesting goal, not just the amount of data transferred over the network or streamed off disk.
Startup time can be saved by doing parsing and semantic analysis on one side of the network. And if you know your target architecture, you can do code generation there too, although that doesn't seem to be the way any systems have evolved -- even Android was doing native code generation on the device recently.
I guess I am having trouble seeing situations where both of these are true:
1) A compression algorithm specific to a file format is say 50% or 100% better than gzip or xz.
2) That 50% or 100% results in a big user-perceived improvement.
Most bytecode formats are "lazily" decoded, although they can be somewhat large. I sort of like the scheme I proposed because it's both compact and can be lazily decoded. You could make it more compact, but then you would have to decompress the whole thing up front.
It's not just compression ratio, but that it's exploiting the nature of the compression mechanism so that the decompression step effectively translates to a depth first traversal of the tree, during which it generates the code.
> I think that overall startup time for example is a more interesting goal, not just the amount of data transferred over the network or streamed off disk.
I agree, but to that end size is a major factor, and if the tree is structured properly nothing stops you from being able to start executing the code during generation ("just" generate stubs for missing functions that will wait for or trigger generation of the missing function)
> Startup time can be saved by doing parsing and semantic analysis on one side of the network. And if you know your target architecture, you can do code generation there too, although that doesn't seem to be the way any systems have evolved -- even Android was doing native code generation on the device recently.
Agreed, and SDE will do the parsing and semantic analysis on the other end too.
> I guess I am having trouble seeing situations where both of these are true:
But that is not the goal. The goal is to generate architecture independent code in a format that is very fast to generate code for. The compression and reduced load time is just a happy side-effect of speeding up the code generation by structuring it for reusability of code fragments during generation.
As such the decompression is "free", as it's nothing more than very lightweight dictionary lookups and insertion during the code generation.
> Most bytecode formats are "lazily" decoded, although they can be somewhat large. I sort of like the scheme I proposed because it's both compact and can be lazily decoded. You could make it more compact, but then you would have to decompress the whole thing up front.
Lazy decoding is possible as described above, though I agree that ability to do "random access" when generating the code is a benefit. Systems like SDE certainly do depend on outputting the code in a sensible order. Though incidentally you can get a lot of that simply by carefully deciding on how to traverse the AST to generate the output. E.g. traverse outer definitions, then the main entrypoint and output any obvious dependencies first.
I was actually thinking the same. WebAssembly certainly brings us a step closer to the SDE approach, though I haven't looked at it enough to be able to say how close.
I'm going through the paper on "slim binaries". They compress the abstract syntax tree at a semantic level and are smaller than compressed source code.
For those who are unfamiliar with the project, here are a few small photos of the custom-designed workstation based on an AMD bit-slice processor that the Oberon System ran on originally.
According to your links, the Oberon was based on a single-chip NS320xx processor, not bit-slice - that was its predecessor, the Lilith. By the time Oberon was started, bit-slice processors were obsolete. Integrated CPU chips were able to beat them on price, speed, size, and power consumption.
I don't know much about bit-slice processors. They seem like an interesting historical footnote at this point. Are there any current applications for the technology?
Bit-slice processor is where the hardware blocks are partitioned along bit boundaries. For example combine 4 chips of 4-bit wide data path to form a 16-bit processor. This was from when chips were not dense enough to fit a whole processor into one die.
Look at the years the CPUs mentioned in https://en.wikipedia.org/wiki/Bit_slicing were produced. That was not a time where there was demand for 64 bit processors (not surprisingly. RAM cost around $6000 per Megabyte in 1980, according to http://jcmit.net/memoryprice.htm, so you would have to pay around $24 million to run out of space on a 32-bit CPU)
Of course, 64 bit registers and less memory would have been useful for scientific computations. However, I think it is hard to build a fast integer multiplier from bit-sliced CPUs (you can, but by the time you are done, the CPU doesn’t look like a cascade of smaller width CPUs anymore). I would guess making floating point perform on bit sliced processors has its challenges, too.
Probably cost and performance. When you string more of these chips together, the propagation delay increases which means your clock speed must be inversely.
The book "Project Oberon: The Design of an Operating System and Compiler" https://www.amazon.com/Project-Oberon-Design-Operating-Compi... contains a detailed explanation of the design for the Oberon compiler and operating system. Not only it is well written with clear explanations, but it also includes the full source code for the compiler and operating system in less than 550 pages!
I learned some interesting compiler techniques from reading that book.
If you just want to play with the Oberon-07 language (the one used to implement the whole system), there are several compilers available for different platforms. You can find a list here: http://oberon07.com/compilers.xhtml
It seems it would be hard to make Oberon the language to play well with "foreign" environments, such as the Java VM and the library. How does one implement interfaces, for example?
Yes a custom foreign function interface is needed. In my compiler I did the bare minimum to bootstrap the compiler. Currently you can create a definition module that makes the bridge between the Java and Oberon worlds.
For example the Oberon definition below:
DEFINITION MathUtil;
PROCEDURE ln(x : REAL) : REAL;
END MathUtil.
exposes the Java MathUtil.ln() static method:
public class MathUtil {
public static float ln(float x) {
return (float) java.lang.Math.log(x);
}
}
A client module can use now the Java implementation of ln:
MODULE Client;
IMPORT MathUtil;
VAR x: REAL;
BEGIN
x: = MathUtil.ln(2.0);
MathUtil.ln()
END Client;
The DEFINITION is an extension of my compiler. It sets the compiler in a different mode, accepting only declarations in the source file.
You approach would work, but I prefer a new keyword showing the intent of the source file. DEFINITION is for declarations only, to allow Java-Oberon interoperability.
How’s the network programming and ssl story in oberon (os)? And multiprocessor/multithreading? As an os, Oberon could be a cool alternative. One wonders if intel considered it for ME in place of minix.
The Native Oberon and EthOS versions used cooperative multitasking.
Bluebottle OS, which introduced the variant known as Active Oberon, made use of multithreading in form of active objects, a concept similar to goroutines.
Its compiler Paco, is one of the first multithreaded compilers I know of.
SSL was not yet a thing when Oberon was popular in the mid-90's, so I don't remember if the browser of the time supported it.
Network programming was a mix of Ethernet and Oberon own protocols, there was support for network printing and file shares.
All books that Wirth wrote about Oberon were written using the text editors of the OS.
Franz mentions Wirth's metric for compiler quality: Speed of self compilation.
I first heard this idea, in a slightly different form, from Vickie Markstein (part of IBM's 801 team) in early '88. She suggested using this idea as an acid test for optimizations. For example, if the compiler with value numbering compiled itself faster than the compiler without value numbering, then she'd say value numbering was worthwhile.
Given the organization of the 801 team, it's possible the idea was due to John Cocke or one of the other members. Doesn't matter much, I think.
I've never had the opportunity to test optimizations using this approach, but I think it would be a fun way to approach the question of adding optimizations to something fast & simple like the Oberon compiler, the Plan 9 compiler, or the Go compiler.
Indeed, for a _system_, like Oberon or Plan 9, where everything is compiled with the same compiler, we could go a step further and try adding the optimization, rebuilding everything, then timing the new compiler. That way any benefits the optimization brought to handling I/O and such would be properly credited and we'd (hopefully) see a steady improvement in the programmer's experience.
I had once tried rebuilding an Oberon compiler and the standard library using itself - all from the sources. I will never forget this - it only took 0.15 seconds.
Having said that, the language goes a bit too far trying to be "as simple as possible but not too simple", at least to my taste -- in a way that Go seems to be, only much more so. It also looks verbose - especially compared to C. So, while I marvel at the language and have a feel for its weird beauty, I don't think I'd be comfortable using it in my day to day activity - I guess, C and C++ have spoiled me...
I think if you look at it in context of the entire Oberon operating environment, it makes a certain amount of sense. While everything is written in Oberon, it seems to me that the average user would essentially be using oberon for roughly what shell scripts and AppleScript is used for: I.e. for writing little commandlets that automate frequently used functionality.
Basically modules are loaded dynamically and any procedure that obeys to a specific signature could be called from the UI, via keyboard and mouse like the ACME editor on Plan 9.
The way they get their input, depends on the signature.
It could be like command line parameters, clipboard, or any selected UI element in another application.
I really don't like having to type the shift key so often on QUERTY. A language where uppercase keywords are the norm sounds like it would lead to RSI.
Then again, we would probably have typescript, coffeescript, etc.. version of Oberon to solve this.
The Pascal language is not case sensitive, nor, as far as I know, are any of its variants. From my experience with Delphi/Object Pascal back in the day, nobody capitalized keywords. You can see an example of typical code with lowercase keywords here:
From "The Oberon Programming Language"[0]: "Capital and lower-case letters are considered as being distinct....These reserved words consist exclusively of capital letters and cannot be used in the role of identifiers". So it seems that keywords do need to be in all-caps, at least if your compiler is compatible with Wirth's description (the standard?).
It is very common to see these languages typeset with uppercase keywords, though, but a lot of that certainly was the monochrome alternative to syntax-highlighting...
Pascal was developed at a time when you couldn't count on both upper case and lower case being available. I learned it on a Control Data Cyber (6-bit character set) using Teletypes.
Development in a language like that, you quickly start using editor macros. Even simple things like Emacs abbrev mode is enough to remove the vast majority of shift usage.
The article praises some features adherent to the runtime/standard library: file system, Hypertext-Based User Interface, but what does it have to do with the language itself? What about clunky COBOLique keyword set: PROCEDURE, BEGIN/END? What about FOR loops, not implemented in the original Oberon? Ironically, LISP dialects predating PASCAL-family are still alive, whereas Pascal/Modula/Oberon are dead as a dodo.
Many people like the clunky syntax of Wirth's languages, and have been exceedingly productive in those languages.
There's Borland's ObjectPascal products, of course (from Turbo to Delphi), which were extremely successful for many years and still survive today. Pascal is nowhere as popular today as in its heyday, but there are people still using Delphi as well as Lazarus, a modern open-source Pascal implementation that's compatible with Delphi.
One of the most popular languages right now, Go, is heavily influenced by Modula and Oberon. Go is more complex, and opts for a more C-like syntax, but many of its concepts come directly from those languages. Another nascent language with a heavy ObjectPascal influence is Nim (which was created by a former ObjectPascaler).
Ada is another Pascal dialect that is far from dead.
Granted, I personally wouldn't want to use these languages today. Go and Nim are taking the programming language evolution further. But this article isn't about using Oberon today.
Don't forget that Apple was a heavy Pascal user in the 80s. Wirth designed Clascal (used with the Apple Lisa computer) for them, which then got morphed into Object Pascal for the Mac. Many applications were written in Object Pascal. Apple developed Lisa Toolkit (an application framework) for Clascal. This was then morphed into MacApp for Object Pascal.
Interesting, I remember reading (maybe just the name) Clascal back in the day, did not know that it morphed into Object Pascal or that Wirth worked on it.
Ada is a Pascal dialect? How do you figure? (If you mean "somewhat in the Pascal flavor", I might be able to see it...)
A more C-like syntax, with a more Pascal-like semantics, might actually be a reasonable sweet spot. (I think the C syntax won for a reason. It's terser, without being so terse it's unreadable, and therefore gives you higher bandwidth. Most peoples' complaints about C are the semantics, not the syntax - though I'm sure at least some people dislike that too...)
While Ada is not formally a Pascal dialect, it arguably has more influence from Pascal than from the earlier ALGOL (which also influenced Pascal; it has keywords like PROCEDURE, BEGIN and END) and Simula. A Pascal-family developer can more easily pick up Ada than, say, a C programmer; the Pascal family already has TYPE, VAR, ranges, records, etc.
From the 1983 Ada reference manual [1]:
Another significant simplification of the design work
resulted from earlier experience acquired by several
successful Pascal derivatives developed with similar
goals. These are the languages Euclid, Lis, Mesa,
Modula, and Sue. Many of the key ideas and syntactic
forms developed in these languages have counterparts
in Ada. Several existing languages such as Algol 68
and Simula, and also recent research languages such
as Alphard and Clu, influenced this language in
several respects, although to a lesser degree than
did the Pascal family.
Ada was widely considered as being an evolution of Pascal at the time (e.g. [2]).
Neither the article, nor your comment provide any substantial arguments, why the language itself should be perceived as a "jewel". All you have is just some references to inspiring success stories and an appeal to authority. What is cool about Oberon, really? (Apart your Wirth-fandom)
> But ever since Pascal, the language aspect has been almost secondary to Wirth's work. Modula(-2) and Oberon both came out of larger system-level design projects that simultaneously also developed workstation computers, modular operating systems, and suites of innovative application programs. Unfortunately, these other important contributions were overshadowed by the programming languages they were associated with, and hence never received the recognition they deserved.
Oberon was both a programming language and an operating system implemented in that programming language. Much like LISP machines, the boundary between programming language and operating system is fuzzy.
MikroElektronika, selling Pascal and Basic compilers for all sort of microcontrollers and embedded platforms also since 1997.
Embarcadero is still selling Delphi.
The keywords are not much more clunky than SQL ones, and no one is required to write them as such, unless they enjoy using editors without auto-formatting capabilities.
True. Lisp has never had strong lobby among corporations (like Pascal had) and is still striving to survive. Some 30-40 years after it has been created people start to dig in the whole paradigm: "program as mathematical expression" as opposed to "program as a natural language sentence" ALGOL/COBOL/PASCAL/etc.
You keep making the COBOL to PASCAL connection, but to me that implies that you don't understand their design goals. The entire ALGOL-W, Pascal, Modula(-II), Oberon, Oberon-07 chain of Wirth languages was decades of striving for a minimalism in design that is entirely different from languages like COBOL and certainly have nothing to do with "program as a natural language sentence". The Wirth languages doesn't shy away from using English keywords, but when you look at their grammar, what stands out is how they focus on simplicity, not approaching natural language.
Wirth-ian languages is about languages as engineering. They're precise and pragmatic - e.g. constructs were stripped out if Wirth did not feel he could translate them into assembly in a compact and simple and easily understandable manner; he put restrictions on adding improvements to the compiler that didn't "pay for themselves" etc. The entire toolchains and systems and languages he worked on is focused on this.
Dead as a dodo? You need to check your facts. For instance, the FreePascal mailing list is very much alive and well. People are using it to make and ship real projects and products. Not as many, maybe, in volume, compared to the most widely used languages such as Java, C#, C, JavaScript, etc., but definitely not a trivial number (anecdotal, based on what I've read, and seen on the mailing list).
Heck, even Delphi, which is a descendant of Pascal, is still going somewhat strong, with many users, despite wrong turns taken by Borland and others who owned it at different times. And there is also Lazarus, a sort of free clone of Delphi, based on Free Pascal with GUI support, IDE and libraries added.
As plenty of others have said here in the past, this board (HN) is representative of just a drop in the ocean compared to the amount of business software activity going on in the world. So you can't draw valid conclusions from what you read here, except for this microcosm.
One would think that in 2017 we would be using an OS that takes the best ideas from Xerox Park/Star, Oberon and Cloud 9. At least on new devices (like tablets) which don't have to keep backward compatibility.
How would a large company (or community project) be able to recruit hundreds of programmers well versed in these languages? The problem is s/w is built on existing knowledge and in the system programming domain that is C/C++ for the most part, and that's where you'll get man-power to the extent needed to build gargantuan OSes like Windows, MacOS, Linux and so on.
And usually good s/w engineering principles were not the predominant factor in the inception of these systems anyway. They were commercially motivated, and hobbyist beginnings. And once you already have a big body of code...
That is the general principle that businesses operate on. They condition of their legacy stacks is usually bad, too, with lots of poorly-thought design. Some companies such as Jane St claim hiring people who can quickly pick up unusual languages leads to staff that's better at problem-solving in general. Unlike them, the Oberon and Pascal languages were designed to be simpler than what's currently standard for educational purposes. If you know an imperative language, you should be able to learn an Oberon dialect about as fast as you can read the syntax.
For a more batteries included, see the Component Pascal dialect with Blackbox:
It had some uptake in Russia and embedded. Still a really, niche player for sure but it did. Also, Astrobe has an Oberon IDE and platform for embedded.
IDE training, native libraries available, and ease of integrating C libraries are all I would be concerned about if just trying to crank out features. They'll certainly pick up the language(s) with no trouble at all.
>How would a large company (or community project) be able to recruit hundreds of programmers well versed in these languages?
I'd take this moment to point out that while there existed _some_ Objective-C programmers in 2007, approximately 99% of the current Objective-C programmers in the world (by my wild speculation) learned this bizarre SmallTalky language just to make iOS apps.
Yep, before Apple bought NeXT, my only contact with Objective-C was to port a particle visualization framework from dying a Cube into Windows/Visual C++.
> How would a large company (or community project) be able to recruit hundreds of programmers well versed in these languages? The problem is s/w is built on existing knowledge and in the system programming domain that is C/C++ for the most part, and that's where you'll get man-power to the extent needed to build gargantuan OSes like Windows, MacOS, Linux and so on.
- Put some cool code riddles on the company website that lots of hackers will like so that they will discuss them on Hacker News.
Those languages are simple to learn. And it's not necessarily about the language anyway. Also, two of those three operating systems were developed by couple dozen people at most, so you shouldn't need hundreds of programmers, as long as the ones you have are competent.
Anybody know when this was written? The latest citation is from 1998, and it talks about Oberon being 10 years old. It also talks about JIT for Java being a "current trend".
> I believe that Wirth’s ultimate impact will be felt even stronger ten years from now than it is today, and that the legacy of his accomplished career devoted to The Art of Simplicity will be enduring.
Unfortunately I don't see any sign of that. The actual trend seems to be in the opposite direction.
About a decade ago, I worked with the guy who developed IBM's Oberon-2 system for OS/2 in the 90s. He'd always get a sort of wistful look about him when he talked about it. It made me want to give it a look, but there was never time.
The BlackBox Component Pascal IDE on the old Mac OS (originally Oberon/F) was the sweetest IDE I've ever used. The Windows version, still pretty good, has been open-sourced.
"the one and only system that almost all members of the Institute for Computer Systems (including the secretary!) used on a daily basis for all their computing tasks"
And I thought that the "S" in CS stood for science...
a science degree isn't about training for jobs, it is about learning and understanding the fundamentals of a field. In that sense the Wirth languages are a great base for understanding static compiled and typed languages (the other importand thing would be learning about Lisp...).
Having properly understood the fundamentals, languages like Java and C can be picked up rather quickly.
At my uni the first programming semester is Pascal, and the second used to be Modula-2. They only introduced C on the third semester. They changed it a couple of years ago, so now they never get to know Modula-2. I see their point in removing it (it's very old fashioned, more than modern Pascal in some ways), but I feel something of value was lost
Interesting. I had read a BYTE magazine article about Modula-2, back in the day. This was after having been a fairly heavy Turbo Pascal user for a while. Never got to try it out, but from the article, I thought Modula-2 seemed like a good language, a sort of better Pascal in some ways, and good for systems programming.
In those days BYTE used to have very good and interesting article about all kinds of both hardware and software topics, and not only mainstream (at the time) ones either. E.g. there was an issue dedicated to Lisp and another one dedicated to Smalltalk, IIRC. Later it got more commercialized, with less good content, shorter and less in-depth articles, and more ads.
Some old BYTE articles or issues are there on the Internet Archive.
I remember wanting Oberon to be Pascal version 2, and that just wasn't what it was supposed to be. I wonder if that's really what prevented the massive growth that other langs have: it had so much "creator halo" that it was hard to have it's own identity vs. "the lang from the guy that made Pascal".
That was an interesting read. Are there any similar projects being worked on creating a simple designed system that can be used day to day? Maybe there is still an active group of Oberon users?
TypeScript gives me a Pascal-vibe at times as well.
Occasionally feel like I should be typing `TButton = record`.
Not that surprising I guess since Anders Hejlsberg wrote Turbo Pascal, much of Delphi, was the lead dev on C# and TypeScript.
He's made a career out of writing productive environments for mortal developers.
I still think Pascal was my favourite language, the old joke back then was "Pascal has one way to do everything, the right way" compared to the expressiveness of a lot of languages.
This is one of several reasons drawing me towards Go. I grew up with Pascal and worked with Modula-2 for quite some time, and have been missing those times ever since. Go seems to really drag most good things from those languages into a modern world.
For example Go method declarations are taken from Oberon-2.
The unsafe package kind of resembles SYSTEM, just that Oberon spec leaves it open the possibility to have Assembly intrisics in SYSTEM, given its goal as systems programming language.
Ironically, Go is a programming language where both an Oberon developer (Robert Griesemer) and the developer of the direct predecessor of C (Ken Thompson) directly took part in the language's inception.
C is primitive but powerful. Go is primitive and safe. I would classify the Wirth-family of languages as safe but powerful. It all comes down to power; Go was explicitly designed to enable armies of lesser code monkeys to work together without anyone getting hurt.
At least they're producing binaries, not claiming their "abstract web hardware" is "near native" when it takes 100MB of browser to say "hello, world!".
Because real languages allow creating your own abstractions to fill the gaps, Go doesn't. Witness the total lack of decent error handling and data structures; despite probably thousands of people trying their best from user code. It's the iPhone of programming languages.
Burroughs, nowadays sold by Unysis as ClearCase, was developed in 1961 using ESPOL, later improved and renamed as NEWP. Both Algol variants.
IBM research on RISC was done with PL/8, a PL/I variant, later used for writing IBM z firmware.
IBM i (OS/400) was initially written in PL/S, another PL/I variant.
Intel used PL/M extensively.
Xerox PARC moved from BCPL into Mesa, where Wirth got his inspiration for Modula-2, followed by Mesa/Cedar, which again influenced Wirth to create Oberon.
Mesa/Cedar designers went to DEC Olivetti, where they ended up designing Modula-2+ and Modula-3.
Apple started with Assembly and Object Pascal, only moving to C++ with PowerPlant due to market pressure.
During the early 80's C was just yet another systems language only available in expensive UNIX workstations. On home computers, on CP/M we only had dialects like Small-C, competing against everything else for attention.
Prof Franz did his PhD under Niklaus Wirth. His thesis was on Semantic Dictionary Encoding - a method for storing a compact semantic tree representation of a program in what is effectively a prefix code (e.g. similar to Huffman coding) that it exploits beautifully to both compress the tree and to use heuristics (the same on the encoder and decoder) to generate templated code fragments to allow the code generator on load time to do less work. Published in '94, it unfortunately was totally overshadowed by Java.
It's still one of my favorite papers, and one day I still want to go down the route of actually implementing SDE properly (there are implementations for Oberon - one of the early remarkable feats was that because of the more compact representation, on MacOberon it was on some hardware faster to load and generate code from these "slim binaries" than it was to just load a native binary, because the code generator was fast enough to beat the disk IO cost of loading a larger binary...)
One of Franz' PhD students was Andreas Gal, who wrote the paper on trace trees and applied it to JIT'ing Javascript, and worked as CTO at Mozilla.