B -- A Simple Interpreter Compiler

For almost 40 years I’ve wanted a language for small computers that was as easy/simple to use as BASIC but “better.” Forth almost does the trick, but it is a bit, uh, unconventional. Something structured and “extensible” with named subroutines that take parameters, have local variables, and can return values. Something like C or Pascal, but interactive. Both of those are probably too big to make interactive on a 32 to 64K machine.

The B programming language:
The B language was the predecessor to C. The best description for my purpose here is by Dennis Richie, The History of the C Programming Language. That’s a very interesting document, and I suggest you read it, but here is a quick summary as I see it.
Ken Thompson had been working on Multics but then Bell Labs pulled out of the project. He wanted to continue some of the work he had been doing and decided to write a smaller OS on a PDP 7 he “found” unused at Bell Labs. (Wouldn’t you like to work in a place in the late 60’s that just had computers sitting around unused?) He wrote the first version of Unix in assembly language, but wanted a high-level language. With only 8KW of memory, not much would fit. He had been using BCPL on the Multics project. BCPL was an “untyped” language. Everything was simply a computer word. He stripped the language down to absolute bare essentials, wrote a compiler that created “threaded code,” and an interpreter for that threaded code. Some I/O libraries were added later. A few programs were written in B, but soon Unix moved to the new PDP 11, which was byte addressed instead of word addressed, and Dennis Richie decided to extend B to fit better. One important aspect of this is that the B compiler was written in B!

A Project is born
What’s important to me is that here is a very small but very powerful language, that will fit (with an OS!) into 8 KW of memory (a bit more than 16 KB.) The OS, the runtime library, and the application program all had to fit at once. The application program could very well be the compiler. It was powerful enough to host its own compiler.
Apparently the original compiler has been lost. However, it has been recreated by Warren Toomey and others.

The runtime library was disassembled from a binary.
And so was the interpreter
The compiler was recreated.

Now, while I was researching doing this project, I realized that finding a working B compiler for a modern machine would be unlikely. But since C was an extension of B, I figured it wouldn’t be too hard to port the B code to C to get it working, then port it back to B once I had a compiler for B. But, Mr. Toomey beat me to it:
Here is a B compiler written in C.
I’ve been doing some reverse engineering. I pretty well understand the interpreter and some of the compiler. I think it would be fairly easy to port the whole system to other architectures. But…
Pretty much any system we are interested in is also byte addressed. So we run into the same problem Richie did. I think a few small extensions would account for that. I sure don’t want to recreate C, but some 8 bit I/O I think would be enough to make a neat little language for our 8 bit systems. It could be self-hosted on many of them. It is small enough that the compiler and runtime should fit into at least 64K of RAM, maybe 32K, and still leave room for some source code. So you could have an interactive, compiled language. A simple text editor could be added and you could write the code, hit a key to compile it, and run it immediately.
That’s my idea/plan as it stands now. I would be interested in hearing thoughts.
Here are some links to B reference material:
Introduction to B
B tutorial
Users’ Reference to B

5 Likes

Sounds great to me - very interesting, and possibly also practical.

(By the way, we’re relatively likely to compare and contrast B, C, and BCPL. If anyone is tempted to post in detail about BCPL, please consider making it a linked topic, so we can have this thread about B and another one about BCPL.)

Stuff I found so far:



The Amsterdam Compiler Kit compiles B for several CPUs and systems including CP/M and Linux386 (and is lots of fun):


It’s nice to have a B at TIO:

A = “blink a LED”
B = “print ‘hello world’”
C = ?



B on UNICS is slightly different than the above and they even are somewhat divergent in what their parsers accept.

1 Like

I wonder if B could be useful for my 16-bit word-addressed mini. That b.c compiler is so simple that I could imagine modifying it to output ND assembly instead of PDP-7 assembly.

2 Likes

But soon you will feel the need to grow.
You can get FORTRAN for … never mind.
B BPL FORTRAN and Tiny C all have mostly the same
features, basic character I/O and simple array indexing
and data constants like char foo[]={ 0,2,0}
This will give you for a self compiling language providing you have ample memory. The fly in the ointment is for most usefull work you need some sort
of structures for any kind of compiled OS, thus you can compile your compiler but not run it.
You need about about 8K (words) for the symbol
table and 16K (words) for the program as guess,
compiling anything often was left a cross compiler
with machines in the early 1970’s
Better languages have data structures.

An interesting thought: the OPC machines likewise. At present we have a non-native BCPL compiler, or rather, we have a python backend which converts SIAL to our machine’s assembly. In fact we also have a project resurrecting Ferranti’s F100, another a word-addressed 16 bit machine, somewhat in need of a compiler! With b.c and b.b maybe one could even build a native compiler?

1 Like

My 16-bit mini has ample memory, no problem there… 128KB (64KW) program memory, 128KB data memory available for a program (if I run the program in two-bank mode. One-bank is also possible, shared program/data). And I can run with segmentation too, i.e. more than two banks. But that’s not necessary for a compiler, the Fortran compiler I already have has lots of room to do its thing. It’s just that it would be interesting to actually get a compiler running from scratch. I have an assembler and all other “binutils”-like tools, so the compiler only has to output assembly source.

compiling anything often was left a cross compiler
with machines in the early 1970’s

For micros, yes (Micro-Soft, as it was called then, used a PDP to cross-compile their software for the Altair etc., and they continued with cross-compiling for the PC in the early days), but minis was where you did the cross compiling.

1 Like

Minis were used for cross compiling mostly for their speed. Not necessarily because the memory requirements were large. Space can be managed by breaking the code up in to modules and linking then together (linking is not particularly memory expensive).

But compiling code on a mini with hard drives was just flat out more efficient than trying to build stuff on 1MHz CPU with a crummy floppy. I made the mistake of trying to compile “Hello World” using a Small-C compiler on an Atari 800 once. With its conventional compile to assembly, launch the assembler, link the final executable. Very disk intensive on a slow machine with slow disks. It was immediately apparent that this system was completely unusable, even for the time.

Not that the minis of the age weren’t slow. They were. But they were a lot faster than the micros.

At the office we were running our tiny VAX 11/730. And we managed to get a DECUS (DEC User Society) tape with Moria, a dungeon crawl Rogue-like game. At the time, it was 22,000 lines of VAX Pascal. And we simply couldn’t build it on our VAX. It would take hours. We wondered why the author did not break the code up in to modules to support separate compiling, but we learned that he was developing it on an 8600. That compiled much, much, much faster. He didn’t break it up because he didn’t have to.

1 Like