202 lines
4 KiB
Text
202 lines
4 KiB
Text
// #module_parameters(RUN_TESTS := false);
|
|
|
|
Vm :: struct {
|
|
reports: [..]Report;
|
|
|
|
parser_allocator: Allocator;
|
|
toplevel: [..]*Node;
|
|
previous: Token;
|
|
filename: string = "(unnamed file)";
|
|
source: string;
|
|
offset: int;
|
|
|
|
interp_allocator: Allocator;
|
|
global: *Interp_Scope;
|
|
}
|
|
|
|
#load "parser.jai";
|
|
#load "resolver.jai";
|
|
#load "interp.jai";
|
|
|
|
#scope_module;
|
|
|
|
Report :: struct {
|
|
message: string;
|
|
offset: int = -1;
|
|
error: bool;
|
|
extras: Extra = .show_entire_line;
|
|
|
|
Extra :: enum_flags {
|
|
hide_location;
|
|
show_entire_line;
|
|
}
|
|
}
|
|
|
|
report :: (vm: *Vm, message := "", args: ..Any) -> *Report {
|
|
r: *Report;
|
|
|
|
if vm.reports.count != 0 {
|
|
last := *vm.reports[vm.reports.count - 1];
|
|
if last.offset == vm.offset {
|
|
r = last;
|
|
}
|
|
else {
|
|
r = array.append(*vm.reports);
|
|
}
|
|
}
|
|
else {
|
|
r = array.append(*vm.reports);
|
|
}
|
|
|
|
r.message = basic.tprint(message, ..args);
|
|
r.offset = vm.offset;
|
|
return r;
|
|
}
|
|
|
|
an_error_was_reported :: (vm: Vm) -> bool {
|
|
if vm.reports.count == 0 return false;
|
|
|
|
reported_error := false;
|
|
for < vm.reports {
|
|
if it.error reported_error = true;
|
|
|
|
line := -1;
|
|
column := -1;
|
|
|
|
if !(it.extras & .hide_location) {
|
|
for 0..vm.source.count - 1 {
|
|
if vm.source[it] == "\n" {
|
|
line += 1;
|
|
column = 1;
|
|
}
|
|
else {
|
|
column += 1;
|
|
}
|
|
}
|
|
|
|
basic.print("%:%,% ", vm.filename, line, column);
|
|
}
|
|
|
|
basic.print("%\n", it.message);
|
|
|
|
if it.extras & .show_entire_line {
|
|
i := it.offset;
|
|
start := i;
|
|
while i >= 0 {
|
|
if vm.source[i] == "\n" {
|
|
start = i + 1;
|
|
break;
|
|
}
|
|
|
|
i -= 1;
|
|
}
|
|
|
|
end := it.offset;
|
|
|
|
i = it.offset;
|
|
while i < vm.source.count {
|
|
if vm.source[i] == "\n" {
|
|
end = i;
|
|
break;
|
|
}
|
|
|
|
i += 1;
|
|
}
|
|
|
|
line := string.{ data = vm.source.data + start, count = end - start };
|
|
basic.print("\t%\n", strings.trim(line));
|
|
}
|
|
}
|
|
|
|
return reported_error;
|
|
}
|
|
|
|
// exported to the entire module since we want these everywhere
|
|
|
|
mem :: #import "jc/memory";
|
|
array :: #import "jc/array";
|
|
kv :: #import "jc/kv";
|
|
|
|
basic :: #import "Basic"; // @future
|
|
strings :: #import "String"; // @future
|
|
|
|
#scope_file;
|
|
|
|
#run {
|
|
vm: Vm;
|
|
|
|
ok := parse_string(*vm, #string END
|
|
fn add(l, r) do return l + r end
|
|
fn sub(l, r) do return l - r end
|
|
fn mul(l, r) do return l * r end
|
|
fn div(l, r) do return l / r end
|
|
|
|
var x = 21.0
|
|
var y = 22.0
|
|
var z = x + y
|
|
|
|
x = x + 1.0 / 2.0
|
|
print x
|
|
|
|
x = add(x, div(1.0, 2.0))
|
|
print x
|
|
|
|
print x == x
|
|
print x == y
|
|
print x == z
|
|
|
|
assert x == y
|
|
assert x != z
|
|
|
|
// def (
|
|
// Add = poly[T] proc(x T, y T) T do return x + y end
|
|
// Sub = poly[T] proc(x T, y T) T do return x - y end
|
|
// Mul = poly[T] proc(x T, y T) T do return x * y end
|
|
// Div = poly[T] proc(x T, y T) T do return x / y end
|
|
// )
|
|
|
|
// def (
|
|
// Addi = Add[int]
|
|
// Addf = Add[float]
|
|
// Subi = Sub[int]
|
|
// Subf = Sub[float]
|
|
// Muli = Mul[int]
|
|
// Mulf = Mul[float]
|
|
// Divi = Div[int]
|
|
// Divf = Div[float]
|
|
// )
|
|
|
|
// def Foo = struct {
|
|
// x int = 1
|
|
// y int = 2
|
|
// z int = 3
|
|
// }
|
|
|
|
// def Value = union {
|
|
// i int
|
|
// f float
|
|
// b bool
|
|
// }
|
|
|
|
// def Kind = enum {
|
|
// a
|
|
// b
|
|
// c
|
|
// d
|
|
// }
|
|
|
|
// var foo = Foo{ x = 10, y = 20, z = 30 }
|
|
// var val = Value{ f = 3.14 }
|
|
// var kind = Kind.a
|
|
END);
|
|
|
|
if an_error_was_reported(vm) return;
|
|
|
|
resolve_everything(*vm);
|
|
// generate_bytecode(*vm);
|
|
// interp_bytecode(*vm);
|
|
}
|
|
|
|
// #if RUN_TESTS {
|
|
// test :: #import "jc/test";
|
|
// }
|