ArbAsm
ArbAsm is my first language project that got to a usable state.
It is an assembly-styled scripting language for arbitrary precision integer arithmetic, written in C.
'Arbitrary precision' means that the numbers in ArbAsm can have any amount of digits (as long as memory permits).
The interpreter is a single (portable) executable, which can either run a REPL, or run ArbAsm source files directly.
Source files are simple text files, with the .aasm
extension.
Its GitHub page has a description of installation and usage,
a lot of sample programs, and even a relatively extensive
wiki page.
Here's some ArbAsm code that does a simple benchmark:
set ir, 0 ; `ir` is the general purpose iteration register
set endian, 1 ; This sets the endianness of the interpreter to big endian
set gr1, 30 000 000 ; This is the amount of loops the program will do
push time ; Saving the value from the time register to the stack
:speedloop ; A label
inc ir
cmp ir, gr1
Cs jmp "speedloop" ; Does a jump to `speedloop`, if the previous comparison yielded a "smaller than" result
print ir ; Prints the amount of iterations that were done
sub $0, time ; Subtracts the current time from the value on top of the stack,
mul $0, 1- ; which was the time at the start of the loop
trunc $0 ; Removes leading zeroes
print $0 ; Prints the amount of time it took to run in seconds
It originally started as a command line calculator tool, but it ended up growing into a scripting language, wayy outside what it was intended for, so it's very clunky (and too slow) to use for actual programming.
That being said, here are some things I have done with it (most of these can be found in the aformentioned scripts directory):
- Digits of Pi calculator
- MandelBrot in the command line
- Rule 110
- Basic MS BMP reader and writer
- Basic bitmap colour filtering and image splicing
Short language description
The underlying machine model is as following:
There are a couple of general purpose registers that the user has full control over,
and a couple of registers that are either read-only, or that have side effects over the operation
of the interpreter.
Next to this, there are two stacks: one that you can directly push, pop and index into, and another one that
you can use as a sort of 'shunting yard' for the main stack.
There is only one type, the Number (which is a dynamic array of bytes), that can be used as a arbitrary precision integer, a string,
or simply as an array of bytes.
Statements have the form of an instruction followed by its arguments, with the destination operand going first (Intel argument ordering).
Broader Context of the project
Arbitrary precision math is a pretty well researched topic (to the point where there are FFT version of multiplication algorithms), but for this project, I hadn't read up on any of that. It's all manual exploration with a noteback and some late nights. Most of my arithmetic operators here have terrible computational complexity, and since it's some of my first C code, it's hard to read and makes a lot of odd decisions. Nevertheless, I'm still proud with how far I was able to go with how limited it all is.