The UCSD p-System, Apple Pascal, and a dream of cross-platform compatibility
markbessey.blog
markbessey.blog
The coolest thing about UCSD Pascal when I first encountered it was it supported "full screen" programs, notably the system's text editor, via the `gotoxy(x, y)` intrinsic. This procedure moved the cursor to the specified character cell on the terminal. Prior to this I'd only used line-oriented editors.
I used a fairly early version of Turbo Pascal for DOS for several years after High School. I can still remember the absolute terror of realizing you'd pressed "R" without saving first.
Seems like at least a two file circular buffer with autosave wouldn't take up too much space, or maybe streaming diffs into a compressed buffer (even on a 286, this shouldn't be too much trouble).
Turbo Pascal wasn't written on a 286; it was written for CP/M, where I think it required 48KiB of RAM. A "fairly early version of Turbo Pascal for DOS" might have required 64KiB?
You can't really stream things onto a floppy disk (remember that early home computers and the IBM PC didn't have hard disks; they didn't become standard equipment until the late 80s). You have to write a whole sector at a time, which can take a second or two to seek the disk to the appropriate track; rotating the disk to the right sector takes a significant fraction of a second. Journaling your edits to a journal file was a feature that EDT on VAX/VMS had around that time, but there wasn't really a practical way to do that on a home computer.
That would be funny if early OSes had an 8track (endless loop) as the circular journal. I think that is how the Voyager probes work. The 8 track DTR on the Voyager probes did not have an endless loop. https://hackaday.com/2018/11/29/interstellar-8-track-the-low...
Did you see this
Show HN: Torque – A lightweight meta-assembler for any processor (benbridle.com)
https://news.ycombinator.com/item?id=43698801
It is a Forth inspired programmable assembler.
based off of https://wiki.xxiivv.com/site/uxn.html
RAM would have been a cheaper and probably more reliable edit journaling device than an 8-track tape. It would survive warm boots unscathed where you had to reboot the computer after hanging it, failing only if your edits were lost to a power outage, and you would test it all the time, not just when the computer crashed. A battery-backed CMOS shift register memory chip, maybe about 2048 bits in size, would have solved the power loss problem, but keep in mind that a lot of these early microcomputers were so bare-bones they didn't even include a real-time clock, which is the other thing you want the battery for.
In 01996, Chen et al. at UMich proposed just such a (non-battery-backed) RAM journal to avoid losing written data in kernel crashes in https://web.eecs.umich.edu/virtual/papers/chen96.pdf, "The Rio File Cache: Surviving Operating System Crashes". They reported that it worked surprisingly well, and it enabled them to increase the durable transaction rate of their spinning rust filesystem by about three orders of magnitude, if I recall. And of course NetApp have been shipping FAServers using that approach (with battery-backed RAM) since day one, also about 01996.
Tim Paterson's blog I linked elsewhere in the thread has some comments about quantitatively exactly how fast different floppy systems used on 8-bit computers were.
This would have been within the contemporary Dos and disk capabilities and size of 160-360kBytes, although slow (5-15 seconds).
When Dave Cutler moved from DEC to MS I expected the Dos console under windows to get that same feature. Disappointed. A gajillion lost hours could have be saved.
It would be awesome to have application level granularity for a time traveling file system, the undo/redo mechanism could be built into the OS.
Reading up on https://en.wikipedia.org/wiki/Fossil_(file_system)
I agree that implementing this functionality in MS-DOS would have been relatively straightforward and acceptably efficient.
It'd be great to have long-lived transactions in a filesystem, permitting higher-level undo and redo.
It's kind of amazing that this one paper introduced command-line completion, copy-on-write pages, load averages, and CAM TLBs.
You had an option from the main menu to "compile" or "run", which included compiling, but NOT saving your edits first. You could save first, but on a floppy-based system, that could take a while.
I want to say that behavior changed in Turbo Pascal version 2, or 3?
I first heard of Turbo Pascal in a magazine called Profiles, published by Kaypro for owners of their computers; I'd recently gotten a Kaypro 4, which ran CP/M-80, my first computer of my very own, and I was pining for Apple Pascal/UCSD Pascal. I read the ad (and maybe a review?); it was $49.95, and I ordered it immediately. Nor was I disappointed.
The idea that you could save money by soldering together your own PDP-11 system from parts, and that there was a company that actually sold the kits (as well as assembled versions), is terrific.
And today (assuming you can find a vintage DCJ11 CPU or equivalent) you still can build your own hardware PDP-11 via PDP-11/Hack and other designs! (Though personally I'll probably go for an FPGA version.)
Compare with UC Berkeley's BSD UNIX, which was originally open sourced in 1988 (though hamstrung from 1992-94 by the Unix lawsuit, opening the way for Linux), and happens to be running in the system I'm typing on...
It appears that UCSD eventually (2006?) made the p-System 1.5 source code available for download, but unfortunately non-commercial only (CC BY-NC-SA?) rather than BSD, etc.
Stack-based vs register-based instruction sets are a very clear size vs speed tradeoff. That's also one reason that the Java VM was designed with a stack architecture, though in that case, it was download time they wanted to minimize.
The whole thing with UCSD having to essentially "give away" the p-System to a separate commercial entity is a sad part of the history, for sure.
[0] https://fabiensanglard.net/anotherWorld_code_review/index.ph...
[1] https://treasures.scss.tcd.ie/hardware/TCD-SCSS-T.20121208.0...
It was a great CAD program, I many ways ahead of AutoCAD in its time. But AutoCAD was written in C, which proved far more popular (and, ultimately, more portable) than UCSD-p.
My dad spent a small fortune buying an IBM PC with 544k of memory and an external Davong hard drive that emulated an enormous floppy drive. He also put UCSD P system on this beast, along with a tecmar graphics master...
I used the p system's editor to write school papers for a long time. It was some weird modal editor; he switched to Dos and turbo pascal after a while...
I got to use this computer for games when he wasn't using it and found that the _wizardry_ save game disks were formatted in UCSD P system format and I could even noodle around with the save games (mostly resulting in the game crashing).
[1]https://en.wikipedia.org/wiki/Wizardry:_Proving_Grounds_of_t...
I wonder if Lisa Pascal will run in a Lisa emulator...
> Build a p-machine emulator, in Rust
Probably a p-code interpreter and/or p-system VM! (Analogous to the JVM but for Pascal/p-system rather than Java and its bytecode. p-code translator/JIT compiler probably left as an exercise for the reader.) I'm surprised that nobody seems to have written one in JavaScript and/or webassembly... the latter basically being p-code for the 2020s.
That is probably why nobody's felt the need to make a p-System for the web.
I think the overall approach of future-proofing your software by compiling it to a simple, portable virtual machine is valid. Since the p-System, in addition to the JVM and Zork Z-machine mentioned in this post, we've seen Smalltalk-80, PostScript, Open Firmware aka OpenBoot, Glulx, the ASS/400, the Open Software Foundation's ANDF (the architecture-neutral distribution format), Google's NaCl and pNaCl, Microsoft's CIL, JS as a compilation target, WebAssembly, uxn, and the revival of old video game consoles in emulation as a stable software target.
A problem with this approach is that most of these portable platform layers are still far too unstable for reliable archival; even video game emulators face a constant struggle to maintain compatibility as they are updated to keep up with whatever platform they're running on. Platforms like the JVM, which make more concessions to efficiency than MAME, have even more difficulty, so the JVM's slogan of "write once, run anywhere" was widely mocked as "write once, debug everywhere". But it's a good aspiration. I'd like to see it realized in a practical way.
My memory of the p-System is that it was almost unusably slow, a problem made worse by its filesystem being so simple it didn't support fragmentation, so sometimes you had to defragment your floppy disk in order to write new files onto it. It's true that its UI was screen-oriented, as wduquette said, and it was driven by a Lotus-1-2-3-like menu system, which enhanced its usability quite a lot.
Being a pure bytecode interpreter was a serious handicap, especially on the sub-1-MIPS machines we were running it on. EUMEL managed to make a go of it. I never got a chance to use EUMEL on an actual Z80, but I hear it was usably fast; I suspect the EUMEL virtual-machine instruction set (which included string operations) and operating environment went a long way towards compensating for the slowness of bytecode interpretation, much as Numpy does on CPython today.
I suspect you could have done a better job with a bytecode more like Dalvik, designed for efficient JIT compilation by leaving less work for the JIT compiler. But Deutsch and Schiffman didn't publish the first JIT-compilation paper until a few years after the p-System was released. (Schiffman told me a self-deprecating joke about this which I guess I can't really repeat.)
Long Tien Nguyen and Alan Kay published a paper on designing a very simple virtual machine for such digital preservation 10 years ago: https://tinlizzie.org/VPRIPapers/tr2015004_cuneiform.pdf
I think these ideas point the way to achieving the kind of future-proofness that the p-System was shooting for.
It's also important to remember that to a large extent, Apple Pascal on the Apple II and other late 1970s home computers wasn't competing with sophisticated native-code compiler suites, but with interpreted BASIC and with assembly language.
Pascal was vastly more-productive than writing in Assembler, and much faster in execution than Apple BASIC. It even had reasonable support for integrating assembly routines for places where you really needed the speed.
The p-System was A LOT more usable on the HP Motorola 68k workstations I used it on. Those were more than adequately fast for the sort of software we were writing for them in 1985.
Thanks for the link to cuneiform, I think I read that paper once, long ago. Will definitely check it out.
> What does the Terak have to do with the Macintosh and MacPaint? The Macintosh's operating system was bootstrapped on an Apple Lisa computer. The Lisa's OS was written on the Lisa using a port of the UCSD Pascal compiler and P-System. The Lisa's port of the P-System was prepared on an Apple II, which had its own version of the P-System that was developed by Bill Atkinson, the Apple programmer who later wrote MacPaint. Atkinson ported the P-System to the Apple II while visiting UCSD, who helped Apple with the port using a Terak. Some people think he got the idea for MacPaint from the paint programs he saw in use on the graphics-intensive, square-pixel Terak. Thanks in part to Gary Capell (gary@cs.su.oz.au) for parts of this story.
Its a great anecdote. And it also makes one think "They wanted to use Pascal so badly, they were willing to use UCSD Pascal for it."UCSD Pascal was a wonder and a pioneer. Unfortunately, it was in the early era of microcomputers. When microcomputers were, frankly, horrible. File this anecdote under "its amazing we managed to get any software written at all" back then.
In the P-System, you had the core VM, and everything else was compiled into that P-code. The shell, the compiler, the file utilities, everything. Again, it's a marvel. It's (almost) self hosted (did it come with an assembler? I don't recall). But if you had a VM running, everything else was self hosted. The compiler compiled itself, being written in UCSD Pascal. Marvel yes, speedy, not so much. It certainly qualified as "better than nothing".
It had a lousy file system. Files had to be continuous, which makes it difficult to write to more than one file at a time. Compressing the disk structure was a routine process. The editor was also very interesting. Also, text files naturally compressed whitespace -- important with Pascal source code where whitespace is probably 20-30% of the space on disk.
However, on the other hand, the runtime was quite sophisticated. P-Code was position independent, so it could read, run, and flush code at will. The code was segmented into chunks, "overlays" being the norm. But as user of the code, it was mostly invisible to you (you know, the way RPC is invisible). If you look at the original Macintosh memory and resource manager, and how it stored applications in segments, you can see the lineage straight from what UCSD was doing back in 1977. And, of course, UCSD Pascal had that novel feature of being an actual, usable Pascal for, well, demonstrable system level programming, and also large system design through the use of Units and such. Novel at the time.
The real shame of the UCSD eco-system, specifically today, was when USCD licensed it to SofTech (something like that), who came out with P-System IV (P-III was a unique port to, I think, a Sage 68K machine). The ship had sailed for "but it's not DOS" types of systems that SofTech was trying to squeeze UCSD back into. But it had some cool features, notably it supported co-routines.
But, while P-System 1.5 and P-System II are all flying free around the interwebs, P-IV is not.
It IS well documented, but whoever owns SofTech today, hasn't released the legacy stuff to world.
Also, as a shout out to the Blog author. Do a search for, I think, the game SunDog. This was written in P-System IV, and they have a P-machine in C (or C++) that you can look at.
The part of the P-Machine I haven't quite grokked, is the way it handles stack frames. Because Pascal allows nested functions (and scopes), it had primitives to access "variable 3, 4 stacks frames up" kind of thing, so its a bit of a maze (plus the first class support for the segments in the runtime as well). I was looking at trying to port it to the 65816. The P-System would naturally work well with a 128K 65816 using their data bank model. You could have the runtime in its own 64K bank, the P-Code in its own, and then 64K of data ram in a 3rd. I thought that would be a neat '816 project.
[0] https://www.threedee.com/jcm/terak/index.html [1] https://news.ycombinator.com/item?id=43708726
There's no reason we couldn't have a cross-platform minimal set of common utilities.
This is unsupported, undocumented, and unstable on every target cosmopolitan supports other than Linux — macOS and (Free|Net|Open)BSD define their syscall ABI as private and subject to arbitrary change, and they do change it. The only supported syscall interface is via their userspace libraries, and binaries that target the syscall ABI directly will fail on future releases.
Furthermore, while cosmopolitan binaries are multi-arch (amd64/arm64 currently) and multi-OS (Linux/Windows/macOS/...), they are arch-specific and OS-specific. Once support for a new target has been added to cosmopolitan, existing binaries must be rebuilt to include it; existing binaries cannot run simply by porting a common runtime.
On top of all that, the APE executable format relies on ill-defined fallback heuristics — which may or may not be implemented by a shell — for executable files that fail with ENOEXEC after first calling `exec()`, but look like they may be '#!'-less shell scripts. Unsurprisingly, this is unreliable, depends on the user's shell, and means that programmatically executing an APE executable using `exec`, `posix_spawn()`, etc, will simply fail.
Cosmopolitan is neat hack, but it's not a viable multiplatform executable format, runtime sysytem, or distribution mechanism. Something like WASM + WASI seems much more likely to fulfill this function in the future.
It's the best we have to ensure programs will be kept running. The multiple payloads are like a rosetta stone.
If I had 1 wish, I would make wine support sixel output + VNC to a localhost port + webgl or equivalent to extend this redundancy to GUIs
> Something like WASM + WASI seems much more likely to fulfill this function in the future.
Time will tell, but given 2 binaries (Sun Java vs Windows i386) from the same time period, the one that was "much more likely to fulfill this function in the future" is much harder to use
p-code is a neat technology, but failing at what it was supposed to achieve