Language Reference¶
BearVM’s input format is a textual IR. Programs consist of optional struct
definitions followed by one or more function definitions. The entry point is
a function named main.
File Extension¶
BearVM source files use the .bear extension.
Types¶
The IR supports the following types:
int— 64-bit signed integer.float— single-precision floating point.double— double-precision floating point.string— string value.
Constants¶
The const keyword marks a value as a constant. Float and double literals
require an explicit type annotation:
%n = const 42
%s = const "hello"
%f = const 3.14: float
%d = const 2.0: double
Type Casts¶
The cast instruction converts a value to another type:
%dbl = cast double %sum
%back_to_float = cast float %dbl
%int_from_float = cast int %f_result
Any numeric type (int, float, double) can be cast to any other
numeric type.
Struct Definitions¶
Structs are defined at the top level, before any functions:
struct Person {
name: string
age: int
}
Fields may be of type int, float, double, or string.
Struct definitions must appear before any function that uses them.
Function Definitions¶
Functions are declared with @name, an optional parameter list, and an
optional return type:
@main(): int {
ret 0
}
@add(%a: int, %b: int): int {
%result = add %a, %b
ret %result
}
Functions with no return value omit the return type annotation:
@print_something {
call puts("hello")
ret 0
}
Registers¶
All locals are registers, prefixed with %:
%x = const 10
%y = add %x, 1
Registers have no declared type; their type is inferred from the instruction
that produces them. A register may be reassigned within the high-level
while sugar, but in explicit SSA form each name is assigned exactly once
and phi is used at merge points.
Explicit Basic Blocks (SSA form)¶
Functions can be written with explicit labeled basic blocks. Labels are
declared with a name followed by a colon. Control flow between blocks uses
jmp and br_if. Values that flow across block boundaries are resolved
with phi:
@fib(%n: int): int {
entry:
%a0 = const 0
%b0 = const 1
%i0 = const 0
jmp loop_cond
loop_cond:
%cond0 = lt %i0, %n
br_if %cond0, loop_body, loop_end
loop_body:
%tmp0 = add %a0, %b0
%a1 = %b0
%b1 = %tmp0
%i1 = add %i0, 1
%a0 = %a1
%b0 = %b1
%i0 = %i1
jmp loop_cond
loop_end:
ret %a0
}
The phi instruction selects a value based on which block was the
predecessor. Its syntax is:
%x = phi [label1: %reg1, label2: %reg2]
The following example shows a float-returning function alongside the main
entry point using cast and putf:
@float_example(): float {
entry:
%f1 = const 3.14: float
%f2 = const 2.0: float
%sum = add %f1, %f2
%dbl = cast double %sum
%back_to_float = cast float %dbl
ret %back_to_float
}
@main(): int {
entry:
%n = const 10
%fib_result = call fib(%n)
call puts(%fib_result)
%f_result = call float_example()
call putf(%f_result)
%int_from_float = cast int %f_result
call puts(%int_from_float)
call flush()
ret 0
}
While Sugar¶
For simpler control flow, the while construct is available:
@fib(%n: int): int {
%a = const 0
%b = const 1
%i = const 0
while (lt %i, %n) {
%tmp = add %a, %b
%a = %b
%b = %tmp
%i = add %i, 1
}
ret %a
}
while is the only high-level control flow construct. It is designed to
make lowering complex control flow easier. It lowers to the same
representation as the explicit basic-block form.
Struct Literals¶
A struct literal initialises all fields inline:
store %p_ptr, { name: "Alice", age: 25 }
This form is used with store to initialise a heap-allocated struct.
Field Access¶
Fields of a struct stored in a register can be accessed and mutated with
set:
%p = Person {
name: "Alice"
age: 25
}
call puts(%p.name)
set %p.age = add %p.age, 1
For heap-allocated structs, use get_field_ref followed by load or
store (see Instruction Reference).
Named Constants¶
Two named constants are defined for use with the open builtin:
READ— opens a file for reading.WRITE— opens a file for writing.
Entry Point¶
Every program must define a @main function. The interpreter reports an
error if it is absent.
Comments¶
Comments begin with
;and extend to the end of the line: