A math-centered programming language library.
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Danila Fedorin 06f17f491c Move variable setting code into utilities. 5 years ago
external Update libds and liblex. 6 years ago
include Move variable setting code into utilities. 5 years ago
src Move variable setting code into utilities. 5 years ago
.clang-format Format the code with clang-format. 5 years ago
.gitignore Add .gitignore file. 6 years ago
.gitmodules Add libds and liblex submodules. 6 years ago
CMakeLists.txt Move GC code to separate source file. 5 years ago
README.md Add a README. 5 years ago



A math-centered programming language library.


libabacus is effectively a stripped down, embeddable programming language. It relies on the program it's embedded into to provide the standard library. In fact, it doesn't even provide an underlying implementation for numbers - the client code provides a means of convering a string into a number, and a way of freeing that value. libabacus takes care of the rest. The features of libabacus are geared towards calculators, so it does not provide higher-level abstractions like OOP.


libabacus has fairly simple syntax. A simple number expression is


If an operator + is registered with libabacus, then an expression using that operator looks like


If two functions, f and g are registered with libabacus, where f takes one argument and g takes two, then the syntax for calling these functions is

g(21, 21)

Blocks are a way to combine a sequence of expressions into one. The value of a block is the result of the last expression in that block. Expressions are delimited by the ; character. For example,

{ 3; 2; 1 }

evalutes to 1. Blocks are the first bit of syntax we've seen that can evalute to a value that isn't a number. For instance, the empty block, {}, does not evaluate to a number. Instead, it evalutes to (). This is a value of the unit type, which only has one possible value, ().

User-defined functions are supported by libabacus:

fun square(a: num): num { a*a }

Let's pick this apart. The first part of a function declaration is the fun keyword. The name of the function is next, followed by the list of parameters that this function accepts. Parameters are listed in the form [name]:[type]. The return type of the function must also be specified. Lastly, the block used to evaluate the function is needed.

The block captures the scope in which the function was declared. For instance, in the following piece of code,

a = 0;
fun test(): num { 
    a = a + 1

test actually has access to a, and calling test many times will yield increasing values of a.

Although all parameters must specify a type, this type can be arbitrary to allow for polymorphic functions. For instance, a function to apply another function to an argument twice can be written as:

fun apply_twice(func: ('T)->'T, a: 'T): 'T {


Everything in libabacus revolves around the libab struct. This struct is used to keep all the state related to the evaluation, and also contains the garbage collector. It needs to be instantiated using the libab_init function.

libab ab;
libab_init(&ab, parse_function, free_function);

Please see interactive.c for an example of a simple yet complete implementation.