Blarb is designed to be the simplest possible (esoteric) systems programming language. Being as such, there is only one logical operator: NAND. It is an assembly-like, stack & register based language.
When you include a file with the ~@~ operator, the tokens in that file will be appended to the parse tree - thus, you should always exit the VM at the end of your programs by calling syscall
0 0 0 0 0 0 60 %, or call
0 exit if you are using the standard library.
There are 8 registers, numbered 0-7. The 0th register is the line pointer - that is, the line that is currently being evaluated. Registers 1-3 are short term registers, that may change when you call a function or jump to a label. Registers 4-7 are guaranteed to never be used in lib.blarb (which I’ll explain later), so you can use them for long term storage in your userspace programs.
Setting the line pointer register to a number less than -1 will terminate the VM. Alternatively, see the
exit function in the standard library.
There are only two types of type literals in blarb:
64-bit singed integers - can be negative.
In Blarb, a string is simply a null-terminated sequence of numbers on the stack. Typing a string literal in will translate into a null-terminated sequence, for sanity. To escape a quotation, use
\"~. To escape backslashes, use ~\\. Newlines and tabs are escaped with
\t, as usual.
Characters are parsed like strings, but get turned into integer types when parsed. Thus, like most other language, a character can only contain a single byte (the character escapes still work).
There are currently 8 single-letter operations. Additionally, you can type a single number to push that number onto the stack (64-bit signed integer). Space between operators and integers or function calls is optional.
b a ! NANDS index a with index b and stores the result in index b
a b \~ Store the value at index a in register b
a$ Push register a onto the stack
Pop from Stack
a? if index a is true (non-zero), execute the rest of the line
~”filename.blarb”@~ Include the given file. Duplicates will be ignored.
f e d c b a syscallnum % Execute the system call with the given args
Upon syscall error (returning
-1), the Blarb VM will terminate. This may change in the future.
Set Memory Address
a b = Swap the value at memory address at index b to the byte (8 bits) at index a of the stack
The value at stack index b should contain a valid memory address (see examples in
lib.blarb, for now..)
Labels are created by a hash:
and called by simply writing their name.
When jumping to a label, the line that the label is on will be executed, ignoring “#labelname”.
No tokens are allowed after a jump to a label, and you will get a parse error if you do so. Thus, a label call must be the last statement on a given line, if present.
Blarb functions are a loosely defined construct, like in assembly, they are just labels. Thus, you must push the line register to the stack using
; Pushes the current line to the stack ; The stack will now contain 2, 3, and the current line number ; No token are allowed after a call to a label 2 3 0$andi 0 0 0 0 0 0 60 % ; exit by calling syscall 60 ; Bitwise AND the two arguments and push the result to the stack #andi 4 3 ! ; A NAND B (the two arguments) 4 4 ! ; NAND the result with itself to bitwise NOT it ; Pop the stack frame and second argument. ; The remaining stack data will only include the return value ; The "2 0 ~" sets the line pointer to the return address ; The "2 ^" pops the return address and the second argument 2 0 ~ 2 ^ ; Run this program with "--debug" to see the result on the stack
Control structures are nothing special in Blarb either - they can be created via labels.
; This program will pop all the numbers on the stack until it hits a 0 ; Pushes a bunch of numbers onto the stack 32 52 42 0 1 52 35203 3502462 #loop 1? 1^ loop ; Pop the NULL for good measure 1^
Args are pushed to the beginning of the VM stack, as “backward strings”, like string literals. The arg count (argc, if you will), is always pushed onto the stack afterwards. Even when there are 0 args.
Note: Without the standard library, it will be extremely difficult to do anything - so you will probably want to include
lib.blarb in all your programs.
The standard library includes tons of useful functions - everything from bitwise operations to functions that will print string literals for you!
Recall: Functions are called with
As of writing this document, the standard library includes:
|nandi||A B||Bitwise NANDs the two top items on the stack.|
|andi||A B||Bitwise ANDs the two top items on the stack.|
|noti||A||Bitwise NOTs the top item on the stack.|
|ori||A B||Bitwise ORs the top two items on the stack.|
|xori||A B||Bitwise XORs the top two items on the stack.|
|lshiftilone||A||Bit shifts the top item left by one bit.|
|lshiftil||A B||Shift A left by B bits.|
|rshiftilone||A||Bit shifts the top item right by one bit.|
|rshiftil||A B||Shift A right by B bits.|
|addi||A B||Adds the top two elements on the stack.|
|subi||A B||Subtracts B from A (A - B).|
|multiplyi||A B||Multiplies the top two elements on the stack.|
|seti||V I||Set’s the word on the stack at|
|index I to value V.|
|copy||I||Copy the element at stack index I.|
|swap||A B||Swap the element at indices A and B.|
|iseqi||A B||Checks if A is equal to B.|
|Returns 1 if true, 0 if false.|
|isgei||A B||Checks if A >= B.|
|tobooli||A||Returns A as a boolean (1 or 0).|
|pushbytetoheapi||A||Pushes a BYTE to the heap.|
|Returns the address of the byte.|
|pushbytearraytoheap||I L||Copy array of length L at index I to the heap.|
|Returns the initial array index breakpoint.|
|stackstrlen||A||Push the length of the string at|
|stack position A to the stack.|
|A B||Prints the string at index A of length B.|
|printline||S||Prints a null terminated string S, with a|
|readchar||D||Reads a single character from descriptor D.|
|brki||B||Sets the new brk address to B. If B is 0,|
|the current brk will be returned.|
|pushstringtoheap||I||Pushes the string at index I to the heap.|
|Retruns the memory address of the string.|
|openwithname||S F M||Opens the file of the null terminated string S.|
|F are the open syscall flags, M is the mode.|
|See the open syscall docs for more information.|
|Returns the file descriptor number.|
|closedescriptor||A||Closes file descriptor A|
|exit||C||Terminates your program with status code C|
See the editors directory for some syntax highlighting plugins. Currently there are only Vim and Emacs plugins.
See the examples directory for worked examples. Call them from same directory that has
lib.blarb. If you freshly cloned this project, this means running
./blarb --debug example/function.blarb, for instance.