One of the more interesting concepts on a Rational 1000 was the way it pushed your code through stages on the way to compilation.
Stage 1: Raw Text
In the first stage, it was raw text. Not much to say really.
Stage 2: Formatted Text
Periodically (generally several times a minute!), while writing code, you would hit the Format key. The Format key would format your code, according to the project-standard.
Generally, the formatter’s parser was very forgiving. There was very little that would stop it in its tracks. If it encountered an error (like an if
with no then
, it would automatically include the missing parts of the statement, leaving placeholders for you to fill in your code. You could even jump between, and overtype, the placeholders quickly. Ada is a verbose language; the Format key was a key time-saver for a lazy typist.
What’s more, at least half of the wasteful arguments about coding style instantly disappeared. The formatter was common across the project, and running it was a necessary step to getting code to compile. It was impossible to break a lot of the coding standards that coding reviews still get bogged down on today.
If I recall correctly, it even smashed-case to follow a fixed style.
Stage 3: Semanticized Code
The next button was the Semanticize button. I never liked the term “semanticize” but I learned to live with it.
The Semanticize button did an implicit Format (if it was required). It then did a full parse, checking that the code was semantically correct, and highlighting any errors.
Ada is a bondage-and-discipline language. It is strongly typed, by just about every definition. Developers would spend plenty of time in this phase, until the parser gave the go ahead and lifted the velvet rope to let the code past.
Once the code was semanticized, some other features would become available.
Command completion was a key one, and one that I missed for many years after leaving this project. That is, you could type the beginning of an identifier name, and hit the Complete button to get a list of choices of matching identifiers. You could type the name of a package, and hit Complete to get a list of choices of identifiers in that package. You could type the name of a function, and hit Complete to have placeholders appear for each of the parameters.
copy(from=> sourceFile, to=>destinationFile);
or copy(to=>destinationFile, from=>sourceFile);
without anyone getting confused. I think is a Good ThingTM – i.e. having the option supported is great. It was particular useful here in providing hints to the developer about how to fill in the parameters.The only problem with the Complete command was that it was slooooow! It would sometimes take over 30 seconds to complete. I often said at the time that the Complete command would be great if it was ten times faster. I would probably demand 500 times faster these days.
Stage 3: Installed Code
The parse graph tree created by the Semanticize button was both temporary and one-sided.
The next button in the sequence was the Install button.
The Install button did an implicit Semanticize (if it was required). It then stored the parse graph tree to permanent storage.
I think it also modified the parse-trees of other installed code to link back to this one. That way, for example, you could see what code referenced a particular definition very quickly. By quickly here, I am probably talking about only a 30 second delay!
Once code was in the installed state, other code could start to reference it. For example, the Semanticize function or the Complete function would only find referenced definitions if they were in the Installed state (or greater).
Installing marked the text as read-only. You would have to “uninstall” it (also known as Demote or Edit) to make further changes. Any code that depended on it would also need to be uninstalled.
Stage 4: Generated Code
The final stage was to generate code.
The Generate Code button did an implicit Install (if it was required). It then produced the object code for the appropriate target platform.
For the cross-compiling that we did, this was terribly slow. (We didn’t do clean build of the project each night – it took days to compile the whole project from scratch.) Doing early testing directly on the Rational 1000 was always preferable for many reasons; avoiding unnecessary cross-compiles was a key one.
Conclusions
This has mainly been a description of how an IDE worked 14 years ago.
I’ve expressed a few minor points of view here and there (e.g. praising the benefits of a project-standard pretty-printer, and named association of parameters).
My stronger opinions are actually on the benefits of a Complete button (which didn’t appear in a reliable form in other, popular IDEs for many years later), and the usage of the concrete syntax tree, rather than text, as the primary artifact of the IDE. I’ll probably blog more about the latter, later.
Comment by Alastair on January 11, 2006
Wikipedia doesn’t even have a stub for the Rational 1000. At least, it’s not linked from the Rational page.
Sounds like an opportunity for fame and fortune to me. OK maybe just fame. OK maybe neither.
Comment by Aristotle Pagaltzis on January 11, 2006
Sounds much like a less animate, more static version of the Smalltalk image concept.
Comment by Julian on January 12, 2006
Aristotle,
I’ve been pondering this.
I only know the Smalltalk image concept in theory. I can see the overlap – the idea of promoting an object into the namespace of objects that the environment knows about.
It has quite a different feel for me though. There was no concept of cloning a copy of the image for later.
The binding was generally early, rather than late. (I can’t state clearly why I think this is important. It just goes to the different “vibe”.) If you wanted to edit a library, all the files that used the library had to be demoted back to edit mode too, and then re-installed.
[Actually, it had the ability to demote individual lines of code, so that it only needed to recompile part of the file. In principle this was much faster! In practice, it was very finicky and finished up to be faster to recompile the lot.]
Comment by Aristotle Pagaltzis on January 13, 2006
Of course there is a huge difference! It’s what I meant by “less animate.â€
Late binding allows compiling methods as soon as you finish writing them. There is never actually a source file as such in a Smalltalk image, all the code exists as running, live bytecode and only turns into text as you browse the system to look at methods. (James Robertson explains this better.)