Well, yes, on this very day 18 years ago, I published the first version of Boriel Basic (which I named ZX Basic back then).
This first version was very different from what it is today, and it’s hard to summarize all the changes made (let alone list the huge number of contributors to the BASIC and assembler libraries), but I’ll do my best... without AI (unlike this image 😉).

The First Version
A few curiosities about what has changed over these 18 years.
It didn’t have its own assembler
It used Pasmo for the final assembly phase. Back then, Pasmo wasn’t able to resolve labels in some cases (it only made two passes over the code at most). I contacted the author, and he told me he was going to add a third pass, but also that he was working on a new version that restructured all the code. I got impatient, and in a weekend, I had a functional assembler, zxbasm. This assembler doesn’t have macros, but it allows the use of preprocessor macros (though it does include some predefined ones like LO() and HI()), and it makes infinite passes (that is, as many as needed to resolve the labels). This allows for very complex expressions based on labels whose final value is unknown until almost the end of the assembly process.
IF statements were not compatible with Sinclair BASIC
Boriel BASIC supported multi-line IF statements like:
IF a < b THEN
PRINT "a is less than b"
END IF
But it did not support:
IF a < b THEN PRINT "a is less than b"
This made porting programs from magazine listings like MicroHobby more tedious (some examples in the examples/ folder show this difference).
There was no READ, DATA, or RESTORE
These were complex to implement. They exist now and closely mimic Sinclair BASIC’s functionality: you can use expressions in DATA statements, which are evaluated at the time they are read. Very few BASICs support this:
DATA x * x, x + 2
They are essentially like anonymous functions (lambdas).
Arrays were much slower
Unlike in C, Boriel BASIC supports multidimensional arrays, but calculating the position of an element requires chained multiplications. On the Z80, which lacks multiplication instructions, this is very costly. But @BritLion came up with an optimization he found online: for small 16-bit multiplications, iterating a sum is faster than performing the multiplication itself. Since array indices are usually less than 32, this is often the most common case, and it significantly optimizes speed without greatly increasing the size of the position calculation routine.
Additionally, it’s possible to declare an array so that its data area is at a specific memory location (for example, on the screen) using DIM a(...) AT <address>.
There were no drawing primitives
... and the first ones that appeared (PLOT, DRAW, CIRCLE, etc.) called the ROM.
Now, the routines are custom and much, much faster than the ROM’s.
Furthermore, it’s possible to draw and print (PRINT) in any memory area, which allows using a "shadow screen."
The libraries you have now didn’t exist
Of course, there was no PRINT42, PRINT64, or the Sprite, music, or bank libraries you have available today. Many, many people have created or contributed to them.
There was no inline assembler
No, ASM ... END ASM didn’t exist. But it was the first thing to arrive, along with Functions and SUB. This allowed the language to expand.
There were a lot of bugs
Large programs couldn’t be compiled. But thanks to bug reports from the community, the compiler gradually expanded its test suite, now including nearly 2000 test cases.
And the most important thing was missing...
You were missing 🫵. Because without you, there would be no community. No good times. No nostalgia. No libraries or incentives to create them.
There would be no IDEs made by others, no game engines, we wouldn’t have been featured in MicroHobby, and we wouldn’t have complained about our listings not being published in the magazine.
Without you, none of this would make sense.
Cheers! 🍺 And here’s to many more years...
Thank you (mean it). @Boriel.