Language bindings#
UNIT is written in C, with bindings for C++ and Python. The bindings are merely thin wrappers over the C library, so the same concepts and instruction set apply in all three languages. This page shows the same program in each language so you can see the mapping.
Attention
None of the C examples on this page come with proper error handling.
Hello World#
A function that returns 42.
C#
UNIT_Context ctx;
UNIT_Context_Init(&ctx);
UNIT_Procedure proc;
UNIT_Procedure_Init(&proc, &ctx, "main");
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 42);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_RETURN_VALUE, 0);
UNIT_Procedure_Optimize(&proc);
UNIT_CompiledProcedure *compiled = UNIT_Compile(&proc, UNIT_HOST_PLATFORM);
UNIT_ExecutableBuffer *buf = UNIT_CompiledProcedure_JIT(compiled, NULL);
int64_t (*fn)(void) = (int64_t (*)(void))UNIT_ExecutableBuffer_GetPointer(buf);
printf("%ld\n", fn()); // 42
UNIT_ExecutableBuffer_Free(buf);
UNIT_CompiledProcedure_Free(compiled);
UNIT_Procedure_Clear(&proc);
UNIT_Context_Clear(&ctx);
C++#
unit::Context ctx;
unit::Procedure proc(ctx, "main");
proc.load_integer(42);
proc.return_value();
proc.optimize();
auto compiled = proc.compile(unit::Platform::host());
auto fn = compiled.jit<int64_t(*)()>();
printf("%ld\n", fn()); // 42
Python#
import unit
proc = unit.Procedure("main")
proc.load_integer(42)
proc.return_value()
proc.optimize()
compiled = proc.compile()
fn = compiled.jit()
print(fn()) # 42
Add#
A function that takes two arguments and returns their sum.
C#
UNIT_Procedure proc;
UNIT_Procedure_Init(&proc, &ctx, "add");
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_ARGUMENT, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_ARGUMENT, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_ADD, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_RETURN_VALUE, 0);
UNIT_Procedure_Optimize(&proc);
UNIT_CompiledProcedure *compiled = UNIT_Compile(&proc, UNIT_HOST_PLATFORM);
UNIT_ExecutableBuffer *buf = UNIT_CompiledProcedure_JIT(compiled, NULL);
int64_t (*add)(int64_t, int64_t) =
(int64_t (*)(int64_t, int64_t))UNIT_ExecutableBuffer_GetPointer(buf);
printf("%ld\n", add(3, 4)); // 7
C++#
unit::Procedure proc(ctx, "add");
proc.load_argument(0);
proc.load_argument(1);
proc.add();
proc.return_value();
proc.optimize();
auto compiled = proc.compile(unit::Platform::host());
auto add = compiled.jit<int64_t(*)(int64_t, int64_t)>();
printf("%ld\n", add(3, 4)); // 7
Python#
proc = unit.Procedure("add")
proc.load_argument(0)
proc.load_argument(1)
proc.add()
proc.return_value()
proc.optimize()
compiled = proc.compile()
add = compiled.jit()
print(add(3, 4)) # 7
Conditional#
Return 1 if the argument is positive, 0 otherwise.
C#
UNIT_Procedure proc;
UNIT_Procedure_Init(&proc, &ctx, "is_positive");
UNIT_JumpLabel *nope = UNIT_Procedure_CreateJumpLabel(&proc, "nope");
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_ARGUMENT, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_COMPARE_LESS_EQUAL, 0);
UNIT_Procedure_AddJump(&proc, UNIT_OP_JUMP_IF_TRUE, nope);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_RETURN_VALUE, 0);
UNIT_Procedure_UseLabel(&proc, nope);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_RETURN_VALUE, 0);
C++#
unit::Procedure proc(ctx, "is_positive");
auto nope = proc.create_jump_label("nope");
proc.load_argument(0);
proc.load_integer(0);
proc.compare_less_equal();
proc.jump_if_true(nope);
proc.load_integer(1);
proc.return_value();
proc.use_label(nope);
proc.load_integer(0);
proc.return_value();
Python#
proc = unit.Procedure("is_positive")
nope = proc.create_jump_label("nope")
proc.load_argument(0)
proc.load_integer(0)
proc.compare_less_equal()
proc.jump_if_true(nope)
proc.load_integer(1)
proc.return_value()
proc.use_label(nope)
proc.load_integer(0)
proc.return_value()
Loop#
Sum the numbers from 1 to N.
C#
UNIT_Procedure proc;
UNIT_Procedure_Init(&proc, &ctx, "sum_to_n");
UNIT_Local sum, i;
UNIT_Procedure_CreateLocal(&proc, "sum", &sum);
UNIT_Procedure_CreateLocal(&proc, "i", &i);
UNIT_JumpLabel *loop = UNIT_Procedure_CreateJumpLabel(&proc, "loop");
UNIT_JumpLabel *end = UNIT_Procedure_CreateJumpLabel(&proc, "end");
// sum = 0; i = n;
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_STORE_LOCAL, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_ARGUMENT, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_STORE_LOCAL, 1);
// loop:
UNIT_Procedure_UseLabel(&proc, loop);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_LOCAL, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_COMPARE_EQUAL, 0);
UNIT_Procedure_AddJump(&proc, UNIT_OP_JUMP_IF_TRUE, end);
// sum += i; i -= 1;
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_LOCAL, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_LOCAL, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_ADD, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_STORE_LOCAL, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_LOCAL, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_INTEGER, 1);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_SUBTRACT, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_STORE_LOCAL, 1);
UNIT_Procedure_AddJump(&proc, UNIT_OP_JUMP, loop);
// end: return sum;
UNIT_Procedure_UseLabel(&proc, end);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_LOAD_LOCAL, 0);
UNIT_Procedure_AddOperation(&proc, UNIT_OP_RETURN_VALUE, 0);
C++#
unit::Procedure proc(ctx, "sum_to_n");
proc.create_local("sum");
proc.create_local("i");
auto loop = proc.create_jump_label("loop");
auto end = proc.create_jump_label("end");
proc.load_integer(0);
proc.store_local(0);
proc.load_argument(0);
proc.store_local(1);
proc.use_label(loop);
proc.load_local(1);
proc.load_integer(0);
proc.compare_equal();
proc.jump_if_true(end);
proc.load_local(0);
proc.load_local(1);
proc.add();
proc.store_local(0);
proc.load_local(1);
proc.load_integer(1);
proc.subtract();
proc.store_local(1);
proc.jump_to(loop);
proc.use_label(end);
proc.load_local(0);
proc.return_value();
Python#
proc = unit.Procedure("sum_to_n")
proc.create_local("sum")
proc.create_local("i")
loop = proc.create_jump_label("loop")
end = proc.create_jump_label("end")
proc.load_integer(0)
proc.store_local(0)
proc.load_argument(0)
proc.store_local(1)
proc.use_label(loop)
proc.load_local(1)
proc.load_integer(0)
proc.compare_equal()
proc.jump_if_true(end)
proc.load_local(0)
proc.load_local(1)
proc.add()
proc.store_local(0)
proc.load_local(1)
proc.load_integer(1)
proc.subtract()
proc.store_local(1)
proc.jump(loop)
proc.use_label(end)
proc.load_local(0)
proc.return_value()
Key Differences#
The instruction set and compilation pipeline are identical across all three languages. The differences are purely syntactic:
C uses
UNIT_Procedure_AddOperation()with opcode constants. Cleanup is manual (Clear/Free). Error handling usesUNIT_FAILED.C++ has a method per instruction (
proc.add()instead ofUNIT_Procedure_AddOperation(&proc, UNIT_OP_ADD, 0)). Cleanup is automatic via RAII. Errors throwunit::error.Python mirrors the C++ API. Cleanup is automatic via garbage collection. Errors raise
unit.Errorsubclasses. The JIT return type is auto-detected from the arguments you pass, or you can use theaddressattribute withctypes(or any FFI library of your preference) for full control.
For all API details, see the language-specific reference pages: C, C++, Python.