// #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"; // }