libabacus/README.md

75 lines
2.8 KiB
Markdown
Raw Permalink Normal View History

2018-08-20 00:00:02 -07:00
# libabacus
A math-centered programming language library.
## About
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.
## Syntax
libabacus has fairly simple syntax. A simple number expression is
```
42
```
If an operator `+` is registered with libabacus, then an expression using
that operator looks like
```
21+21
```
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
```
f(42)
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 {
func(a);
func(a)
}
```
## Integration
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.
```C
libab ab;
libab_init(&ab, parse_function, free_function);
```
Please see `interactive.c` for an example of a simple yet complete implementation.