diff --git a/cmd/v/v.v b/cmd/v/v.v index 500488a0b7..67362ec66c 100644 --- a/cmd/v/v.v +++ b/cmd/v/v.v @@ -123,7 +123,8 @@ fn main() { } else {} } - if command in ['run', 'build', 'build-module'] || command.ends_with('.v') || os.exists(command) { + if command in ['run', 'build', 'build-module', 'interpret'] || command.ends_with('.v') + || os.exists(command) { // println('command') // println(prefs.path) builder.compile(command, prefs) diff --git a/examples/fibonacci.v b/examples/fibonacci.v index 13056d236f..72e59c9434 100644 --- a/examples/fibonacci.v +++ b/examples/fibonacci.v @@ -1,18 +1,17 @@ // This program displays the fibonacci sequence -// import os +import os fn main() { // Check for user input - // if os.args.len != 2 { - // println('usage: fibonacci [rank]') + if os.args.len != 2 { + println('usage: fibonacci [rank]') - // Exit - // return - // } + return + } // Parse first argument and cast it to int - // stop := os.args[1].int() - stop := 23 + + stop := os.args[1].int() // Can only calculate correctly until rank 92 if stop > 92 { println('rank must be 92 or less') @@ -20,9 +19,9 @@ fn main() { } // Three consecutive terms of the sequence - mut a := 0 - mut b := 0 - mut c := 1 + mut a := i64(0) + mut b := i64(0) + mut c := i64(1) println(a + c + c) for _ in 0 .. stop { // Set a and b to the next term diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 6285711aa6..a7e860221c 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -957,6 +957,7 @@ pub mut: key_type Type val_type Type cond_type Type + high_type Type kind Kind // array/map/string label string // `label: for {` scope &Scope diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 8fb68ce595..b04aa4c6a8 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -719,11 +719,11 @@ fn (mut b Builder) cc_linux_cross() { verror(cc_res.output) return } - mut linker_args := ['-L $sysroot/usr/lib/x86_64-linux-gnu/', '--sysroot=$sysroot', '-v', - '-o $b.pref.out_name', '-m elf_x86_64', + mut linker_args := ['-L$sysroot/usr/lib/x86_64-linux-gnu/', '-L$sysroot/lib/x86_64-linux-gnu', + '--sysroot=$sysroot', '-v', '-o $b.pref.out_name', '-m elf_x86_64', '-dynamic-linker /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2', '$sysroot/crt1.o $sysroot/crti.o $obj_file', '-lc', '-lcrypto', '-lssl', '-lpthread', - '$sysroot/crtn.o'] + '$sysroot/crtn.o', '-lm'] linker_args << cflags.c_options_only_object_files() // -ldl b.dump_c_options(linker_args) diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index fc2c2740a2..75ad25cd4a 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -8,6 +8,8 @@ import os import rand import v.pref import v.util +import v.eval +import v.checker fn (mut b Builder) get_vtmp_filename(base_file_name string, postfix string) string { vtmp := util.get_vtmp_folder() @@ -42,6 +44,7 @@ pub fn compile(command string, pref &pref.Preferences) { .c { b.compile_c() } .js_node, .js_freestanding, .js_browser { b.compile_js() } .native { b.compile_native() } + .interpret { b.interpret() } } mut timers := util.get_timers() timers.show_remaining() @@ -116,7 +119,6 @@ fn (mut b Builder) run_compiled_executable_and_exit() { panic('Running iOS apps is not supported yet.') } if b.pref.is_verbose { - println('============ running $b.pref.out_name ============') } if b.pref.is_test || b.pref.is_run { compiled_file := os.real_path(b.pref.out_name) @@ -347,3 +349,15 @@ pub fn (v &Builder) get_user_files() []string { } return user_files } + +pub fn (mut b Builder) interpret() { + mut files := b.get_builtin_files() + files << b.get_user_files() + b.set_module_lookup_paths() + b.front_and_middle_stages(files) or { return } + + util.timing_start('INTERPRET') + mut e := eval.new_eval(b.table, b.pref) + e.eval(b.parsed_files) + util.timing_measure('INTERPRET') +} diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index f1ab66b0f3..d091a0da45 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -234,7 +234,8 @@ fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type ast.Type, right // a negative value, the resulting value is implementation-defined (ID). left_sym_final := c.table.get_final_type_symbol(left_type) left_type_final := ast.Type(left_sym_final.idx) - if node.op == .left_shift && left_type_final.is_signed() { + if node.op == .left_shift && left_type_final.is_signed() && !(c.inside_unsafe + && c.file.path.contains('vlib/v/eval/infix.v')) { c.note('shifting a value from a signed type `$left_sym_final.name` can change the sign', node.left.position()) } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4e622685f2..f8ffceba90 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -28,7 +28,8 @@ const ( valid_comptime_if_platforms = ['amd64', 'i386', 'aarch64', 'arm64', 'arm32', 'rv64', 'rv32'] valid_comptime_if_cpu_features = ['x64', 'x32', 'little_endian', 'big_endian'] valid_comptime_if_other = ['js', 'debug', 'prod', 'test', 'glibc', 'prealloc', - 'no_bounds_checking', 'freestanding', 'threads', 'js_node', 'js_browser', 'js_freestanding'] + 'no_bounds_checking', 'freestanding', 'threads', 'js_node', 'js_browser', 'js_freestanding', + 'interpreter'] valid_comptime_not_user_defined = all_valid_comptime_idents() array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort', 'contains', 'index', 'wait', 'any', 'all', 'first', 'last', 'pop'] @@ -4881,6 +4882,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) { } else { node.val_type = high_type } + node.high_type = high_type node.scope.update_var_type(node.val_var, node.val_type) } else { sym := c.table.get_final_type_symbol(typ) @@ -7208,6 +7210,7 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Position) bool { 'prealloc' { return !c.pref.prealloc } 'no_bounds_checking' { return cname !in c.pref.compile_defines_all } 'freestanding' { return !c.pref.is_bare || c.pref.output_cross_c } + 'interpreter' { c.pref.backend != .interpret } else { return false } } } else if cname !in c.pref.compile_defines_all { diff --git a/vlib/v/eval/eval.v b/vlib/v/eval/eval.v index 45bb687582..dd4dc771d1 100644 --- a/vlib/v/eval/eval.v +++ b/vlib/v/eval/eval.v @@ -4,96 +4,198 @@ module eval import v.ast -import v.checker import v.pref +import v.util -pub type Object = int | string +pub fn new_eval(table &ast.Table, pref &pref.Preferences) Eval { + return Eval{ + table: table + pref: pref + } +} + +// const/global is `Object` +type Symbol = Object | ast.EmptyStmt | ast.FnDecl pub struct Eval { -mut: - checker checker.Checker - vars map[string]Var - table &ast.Table + pref &pref.Preferences +pub mut: + table &ast.Table + mods map[string]map[string]Symbol + future_register_consts map[string]map[string]map[string]ast.ConstField // mod:file:name:field + local_vars map[string]Var + local_vars_stack []map[string]Var + scope_idx int // this is increased when e.open_scope() is called, decreased when e.close_scope() (and all variables with that scope level deleted) + returning bool + return_values []Object + cur_mod string + cur_file string + back_trace []string } -pub struct Var { - value Object +pub fn (mut e Eval) eval(files []&ast.File) { + e.register_symbols(files) + // println(files.map(it.path_base)) + e.run_func(e.mods['main']['main'] or { ast.EmptyStmt{} } as ast.FnDecl) } -pub fn (mut e Eval) eval(file ast.File, table &ast.Table) string { - vpref := &pref.Preferences{} - e.table = table - mut res := '' - e.checker = checker.new_checker(table, vpref) - for stmt in file.stmts { - res += e.stmt(stmt) + '\n' +// first arg is reciever (if method) +pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) { + e.back_trace << func.name + old_mod := e.cur_mod + e.cur_mod = func.mod + + old_file := e.cur_file + e.cur_file = func.file + defer { + e.cur_mod = old_mod + e.cur_file = old_file + e.back_trace.pop() } - return res.trim_space() -} - -fn print_object(o Object) { - match o { - int { println(o) } - else { println('unknown object') } + mut args := _args.clone() + if func.params.len != args.len && !func.is_variadic { + e.error('mismatched parameter length for $func.name: got `$args.len`, expected `$func.params.len`') } -} -pub fn (o Object) str() string { - match o { - int { return o.str() } - else { println('unknown object') } - } - return '' -} - -fn (mut e Eval) stmt(node ast.Stmt) string { - match node { - ast.AssignStmt { - // TODO; replaced VarDecl + if func.name in ['print', 'println', 'eprint', 'eprintln'] { + s := args[0].string() // stringify because println accepts anything as argument + match func.name { + 'print' { + print(s) + } + 'println' { + println(s) + } + 'eprint' { + eprint(s) + } + 'eprintln' { + eprintln(s) + } + else {} } - ast.ExprStmt { - o := e.expr(node.expr) - print('out: ') - print_object(o) - return o.str() - } - // ast.StructDecl { - // println('s decl') - // } - // ast.VarDecl { - // e.vars[it.name] = Var{ - // value: e.expr(it.expr) - // } - // } - else {} - } - return '>>' -} - -fn (mut e Eval) expr(node ast.Expr) Object { - match node { - ast.IntegerLiteral { - return node.val - } - ast.Ident { - print_object(node.value) - // Find the variable - v := e.vars[node.name] - return v.value - } - ast.InfixExpr { - e.checker.infix_expr(mut node) - // println('bin $it.op') - left := e.expr(node.left) as int - right := e.expr(node.right) as int - match node.op { - .plus { return left + right } - .mul { return left * right } - else {} + } else { + e.local_vars_stack << e.local_vars + e.local_vars = {} + old_scope := e.scope_idx + e.scope_idx = 0 + e.open_scope() + // have to do this because of cgen error + args__ := if func.is_method { args[1..] } else { args } + for i, arg in args__ { + e.local_vars[(func.params[i]).name] = Var{ + val: arg + scope_idx: e.scope_idx } } - else {} + if func.is_method { + print(e.back_trace) + println(func.receiver.typ - 65536) + e.local_vars[func.receiver.name] = Var{ + val: args[0] + scope_idx: e.scope_idx + } + } + e.stmts(func.stmts) + e.returning = false + e.close_scope() + e.scope_idx = old_scope + e.local_vars = e.local_vars_stack.pop() } - return 0 - // return Object{} +} + +pub fn (mut e Eval) register_symbols(files []&ast.File) { + for file in files { + // eprintln('registering file: $file.path_base') + mod := file.mod.name + e.register_symbol_stmts(file.stmts[1..], mod, file.path) + + // eprintln('registered file: $file.path_base') + } + for mod, const_files in e.future_register_consts { + e.cur_mod = mod + + for file, fields in const_files { + e.cur_file = file + for _, field in fields { + e.mods[mod][field.name.all_after_last('.')] = e.expr(field.expr, field.typ) + if mod == 'os' && field.name.all_after_last('.') == 'args' { + mut res := Array{} + res.val << e.pref.out_name.all_after_last('/') + for arg in e.pref.run_args { + res.val << arg + } + e.mods[mod][field.name.all_after_last('.')] = Object(res) + } + } + } + } +} + +pub fn (mut e Eval) register_symbol_stmts(stmts []ast.Stmt, mod string, file string) { + for stmt in stmts { // first is just module declaration, so ignore + e.register_symbol(stmt, mod, file) + } +} + +pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) { + match stmt { + ast.FnDecl { + // this mess because c error + x := ast.Stmt(stmt) + y := Symbol(x as ast.FnDecl) + e.mods[mod][stmt.name.all_after_last('.')] = y + } + ast.Import {} // already handled by builder, TODO: get `as` name + ast.StructDecl {} // these are already parsed by the checker into e.table + ast.InterfaceDecl {} + ast.EnumDecl {} + ast.TypeDecl {} + ast.GlobalDecl {} + ast.HashStmt {} + ast.ConstDecl { + // evaluate them later since they may use functions defined after this point + for field in stmt.fields { + e.future_register_consts[mod][file][field.name] = field + } + } + ast.ExprStmt { + println('expr') + x := stmt.expr + match x { + ast.IfExpr { + if !x.is_comptime { + e.error('only comptime ifs are allowed in top level') + } + for i, branch in x.branches { + mut do_if := false + println('branch:$branch') + match (branch.cond as ast.Ident).name { + 'windows' { + do_if = e.pref.os == .windows + } + else { + e.error('unknown compile time if') + } + } + do_if = do_if || x.branches.len == i + 1 + if do_if { + e.register_symbol_stmts(branch.stmts, mod, file) + break + } + } + } + else { + e.error('unknown decleration expression statement $x.type_name()') + } + } + } + else { + e.error('unhandled decleration statement $stmt.type_name()') + } + } +} + +fn (e Eval) error(msg string) { + util.verror('interpreter', msg) } diff --git a/vlib/v/eval/expr.v b/vlib/v/eval/expr.v new file mode 100644 index 0000000000..1e0a719165 --- /dev/null +++ b/vlib/v/eval/expr.v @@ -0,0 +1,566 @@ +module eval + +import v.ast +import v.util +import math +import strconv + +pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object { + match expr { + ast.CallExpr { + // println(expr.is_method) + // is_method := expr.left.type_name() != 'unknown v.ast.Expr' + // println(is_method) + if expr.name == 'int' { + e.error('methods not supported') + } + mut args := expr.args.map(e.expr(it.expr, it.typ)) + if expr.is_method { + args.prepend(e.expr(expr.left, expr.receiver_type)) + } + match expr.language { + .c { + if expr.is_method { + e.error('c does not have methods') + } + match expr.name.all_after('C.') { + 'write' { + return Int{C.write(args[0].int_val(), args[1] as voidptr, + args[2].int_val()), 32} + } + 'calloc' { + return Ptr{ + val: vcalloc(int(args[0].int_val() * args[1].int_val())) + } + } + 'getcwd' { + unsafe { + return Ptr{ + val: C.getcwd((args[0] as Ptr).val as voidptr, args[1].int_val()) + } + } + } + 'memcpy' { + unsafe { + return Ptr{ + val: C.memcpy(args[0] as voidptr, args[1] as voidptr, + args[2].int_val()) + } + } + } + // 'printf' { + // mut voidptr_args := []voidptr{} + // for arg in args[1..] { + // // if arg is Int { + // // voidptr_args << voidptr(arg.val) + // // } else { + // voidptr_args << voidptr(&arg) + // // } + // } + // // println((e.local_vars['s'].val as string).str == voidptr_args[1]) + // println('helo?$voidptr_args') + // // println((byteptr(voidptr_args[1])[0])) + // x := strconv.v_sprintf(args[0] as string, ...voidptr_args) + // // println('helo!') + // // println(x.len) + // y := C.write(1, x.str, x.len) + // println('aft') + // return Int{y, 32} + // } + else { + e.error('unknown c function: `$expr.name`') + } + } + } + .v { + // TODO: Anon functions + name := expr.name.all_after_last('.') + mod := expr.mod + mut func := e.mods[mod][name] or { + e.mods['builtin'][name] or { ast.EmptyStmt{} } + } + + if func is ast.FnDecl { + e.run_func(func as ast.FnDecl, ...args) + if e.return_values.len == 1 { + return e.return_values[0] + } else { + return e.return_values + } + } + e.error('unknown function: ${mod}.$name at line $expr.pos.line_nr') + } + // .js { + // e.error('js is not supported') + // } + else { + e.error('$expr.language is not supported as a call expression language') + } + } + } + ast.StringLiteral { + // escape the escapes + mut res := '' + mut is_escape := false + for c in expr.val { + if is_escape { + res += e.get_escape(rune(c)).str() + } else if c == `\\` { + is_escape = true + } else { + res += rune(c).str() + } + } + + return Object(res) + } + ast.IfExpr { + if expr.is_expr { + e.error('`if` expressions not supported') + } + + if expr.is_comptime { + for i, branch in expr.branches { + mut do_if := false + if expr.has_else && i + 1 == expr.branches.len { // else branch + do_if = true + } else { + if branch.cond is ast.Ident { + match branch.cond.name { + 'windows' { + do_if = e.pref.os == .windows + } + 'macos' { + do_if = e.pref.os == .macos + } + 'linux' { + do_if = e.pref.os == .linux + } + 'android' { + do_if = e.pref.os == .android + } + 'freebsd' { + do_if = e.pref.os == .freebsd + } + 'prealloc' { + do_if = e.pref.prealloc + } + else { + e.error('unknown compile time if: $branch.cond.name') + } + } + } else if branch.cond is ast.PostfixExpr { + do_if = (branch.cond.expr as ast.Ident).name in e.pref.compile_defines + } + } + if do_if { + e.stmts(branch.stmts) + break + } + } + return empty + } else { + for i, b in expr.branches { + mut result := e.expr(b.cond, ast.bool_type_idx) + + if expr.has_else && i + 1 == expr.branches.len { // else block + e.stmts(b.stmts) + break + } + if result is bool { + if result as bool { + e.stmts(b.stmts) + break + } + } else { + e.error('non-bool expression: $b.cond') + } + } + return empty + } + } + ast.InfixExpr { + left := e.expr(expr.left, expr.left_type) + right := e.expr(expr.right, expr.right_type) + return e.infix_expr(left, right, expr.op, expecting) + } + ast.IntegerLiteral { + // return u64(strconv.parse_uint(expr.val, 0, 64) + return i64(strconv.parse_int(expr.val, 0, 64) or { + e.error('invalid integer literal: $expr.val') + }) // TODO: numbers larger than 2^63 (for u64) + } + ast.FloatLiteral { + return f64(strconv.atof64(expr.val)) + } + ast.BoolLiteral { + return expr.val + } + ast.Ident { + match expr.kind { + .variable { + // println(e.local_vars[expr.name].val.type_name()) + return e.local_vars[expr.name].val + } + .constant { + return if expr.name.contains('.') { + e.mods[expr.name.all_before_last('.')] + } else { + e.mods[e.cur_mod] + }[expr.name.all_after_last('.')] or { ast.EmptyStmt{} } as Object + } + else { + e.error('unknown ident kind for `$expr.name`: $expr.kind') + } + } + } + ast.CastExpr { + x := e.expr(expr.expr, expr.expr_type) + if expr.typ in ast.signed_integer_type_idxs { + match x { + Uint { + return Int{ + val: i64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Int { + return Int{ + val: i64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Float { + return Int{ + val: i64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{ + val: x + size: i8(e.type_to_size(expecting)) + } + } else { + return Uint{ + val: u64(x) + size: i8(e.type_to_size(expecting)) + } + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{ + val: i64(x) + size: i8(e.type_to_size(expecting)) + } + } else { + return Uint{ + val: u64(x) + size: i8(e.type_to_size(expecting)) + } + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } else if expr.typ in ast.unsigned_integer_type_idxs { + match x { + Uint { + return Uint{ + val: u64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Int { + return Uint{ + val: u64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Float { + return Uint{ + val: u64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + i64 { + return Uint{ + val: u64(x) + size: i8(e.type_to_size(expr.typ)) + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{ + val: i64(x) + size: i8(e.type_to_size(expecting)) + } + } else { + return Uint{ + val: u64(x) + size: i8(e.type_to_size(expecting)) + } + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } else if expr.typ in ast.float_type_idxs { + match x { + Uint { + return Float{ + val: f64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Int { + return Float{ + val: f64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + Float { + return Float{ + val: f64(x.val) + size: i8(e.type_to_size(expr.typ)) + } + } + f64 { + return Float{ + val: x + size: i8(e.type_to_size(expr.typ)) + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } else if expr.typ in ast.pointer_type_idxs { + y := *(x as Ptr).val + if expr.typ == ast.byteptr_type_idx { + match y { + char, voidptr { + unsafe { + return Ptr{ + val: (x as Ptr).val + } + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } else if expr.typ == ast.voidptr_type_idx { + match y { + char, Int { + unsafe { + return Object(voidptr((x as Ptr).val)) + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } else if expr.typ == ast.charptr_type_idx { + match y { + voidptr, Int { + unsafe { + return Ptr{ + val: &char((x as Ptr).val) + } + } + } + else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + } + } else if e.table.get_type_symbol(expr.typ).kind in [.interface_, .sum_type] { + eprintln(util.formatted_error('warning:', 'sumtype or interface casts return void currently', + e.cur_file, expr.pos)) + } else { + e.error('unknown cast: ${e.table.get_type_symbol(expr.expr_type).str()} to ${e.table.get_type_symbol(expr.typ).str()}') + } + } + ast.SelectorExpr { + exp := e.expr(expr.expr, expr.expr_type) + match exp { + string { + match expr.field_name { + 'str' { + return Ptr{ + val: exp.str + } + } + 'len' { + return Int{exp.len, 32} + } + else { + e.error('unknown selector to string: $expr.field_name') + } + } + } + Array { + match expr.field_name { + 'len' { + return Int{exp.val.len, 32} + } + else { + e.error('unknown selector to array: $expr.field_name') + } + } + } + else { + e.error('unknown selector expression: $exp.type_name()') + } + } + e.error(exp.str()) + } + ast.ArrayInit { + if expr.has_len || expr.has_cap || expr.has_default { + if expr.has_len && !expr.has_cap && expr.has_default { + return Array{ + val: []Object{len: int((e.expr(expr.len_expr, 7) as Int).val), init: e.expr(expr.default_expr, + expr.elem_type)} + } + } else if !expr.has_len && expr.has_cap && !expr.has_default { + return Array{ + val: []Object{cap: int((e.expr(expr.cap_expr, 7) as Int).val)} + } + } else if !expr.has_len && !expr.has_cap && !expr.has_default { + return Array{ + val: []Object{} + } + } else { + e.error('unknown array init combination; len: $expr.has_len, cap: $expr.has_cap, init: $expr.has_default') + } + } + if expr.is_fixed || expr.has_val { + e.error('fixed arrays are not supported') + } + mut res := Array{ + val: []Object{cap: expr.exprs.len} + } + + for i, exp in expr.exprs { + res.val << e.expr(exp, expr.expr_types[i]) + } + return res + } + ast.CharLiteral { + if expr.val.len !in [1, 2] { + e.error('invalid size of char literal: $expr.val.len') + } + if expr.val[0] == `\\` { // is an escape + return e.get_escape(rune(expr.val[1])) + } else { + return rune(expr.val[0]) + } + } + ast.StructInit { + // eprintln('unhandled struct init at line $expr.pos.line_nr') + return 'helo' + } + ast.SizeOf { + return Uint{e.type_to_size(expr.typ), 64} + } + ast.ParExpr { + return e.expr(expr.expr, expecting) + } + ast.PrefixExpr { + match expr.op { + .amp { + x := e.expr(expr.right, expr.right_type) + return Ptr{ + val: &x + } + } + else { + e.error('unhandled prefix expression $expr.op') + } + } + } + ast.PostfixExpr { + match expr.op { + .inc { + e.add(expr.expr, Int{1, 64}) + return e.expr(expr.expr, ast.i64_type_idx) + } + .dec { + e.add(expr.expr, Int{-1, 64}) + return e.expr(expr.expr, ast.i64_type_idx) + } + else { + e.error('unhandled postfix expression $expr.op') + } + } + } + ast.StringInterLiteral { + mut res := expr.vals[0] + + for i, exp in expr.exprs { + res += e.expr(exp, expr.expr_types[i]).string() + res += expr.vals[i + 1] + } + + return res + } + else { + e.error('unhandled expression $expr.type_name()') + } + } + return empty +} + +fn (e Eval) type_to_size(typ ast.Type) u64 { + match typ { + ast.voidptr_type_idx, ast.byteptr_type_idx, ast.charptr_type_idx { + return u64(if e.pref.m64 { + 64 + } else { + 32 + }) + } + ast.i8_type_idx, ast.i16_type_idx, ast.int_type_idx, ast.i64_type_idx { + return u64(math.exp2(f64(typ - 2))) // this formula converts the type number to the bitsize + } + ast.byte_type_idx, ast.u16_type_idx, ast.u32_type_idx, ast.u64_type_idx { + return u64(math.exp2(f64(typ - 6))) // this formula converts the type number to the bitsize + } + ast.int_literal_type_idx, ast.float_literal_type_idx { + return 64 + } + ast.f32_type_idx, ast.f64_type_idx { + return u64(math.exp2(f64(typ - 8))) // this formula converts the type number to the bitsize + } + else { + e.error('type_to_size(): unknown type: ${e.table.get_type_symbol(typ).str()}') + return -1 + } + } +} + +fn (e Eval) get_escape(r rune) rune { + res := match r { + `\\` { + `\\` + } + `n` { + `\n` + } + `0` { + `\0` + } + else { + `e` + } + } + if res == `e` { + e.error('unknown escape: `$r`') + } + return res +} diff --git a/vlib/v/eval/gen/infix_gen.v b/vlib/v/eval/gen/infix_gen.v new file mode 100644 index 0000000000..12ec36afcd --- /dev/null +++ b/vlib/v/eval/gen/infix_gen.v @@ -0,0 +1,141 @@ +// this file generates ../infix.v +module main + +import strings +import os + +const ( + header = 'module eval +import v.token +import v.ast +fn(e Eval)infix_expr(left Object,right Object,op token.Kind,expecting ast.Type)Object{match op{' + footer = "else{e.error('unknown infix expression: \$op')}}return empty // should e.error before this anyway +} +" + uk_expect_footer = "else{e.error('unknown infix expectation: \${e.table.get_type_symbol(expecting).str()}')}}" + comparison = { + 'gt': '>' + 'lt': '<' + 'eq': '==' + 'ne': '!=' + } + math_ops = { + 'plus': '+' + 'minus': '*' + 'mul': '+' + 'div': '+' + 'right_shift': '>>' + 'left_shift': '<<' + } + compound_types = ['Int', 'Uint', 'Float'] + literal_types = ['i64', 'f64'] +) + +fn main() { + mut b := strings.new_builder(124000) + b.write_string(header) + + for enm, op in comparison { + b.write_string('.$enm{match left{') + for ct in compound_types { + b.write_string('$ct {match right{') + for ct2 in compound_types { + b.write_string('$ct2{return left.val${op}right.val}') + } + for lt2 in literal_types { + b.write_string('$lt2{return left.val${op}right}') + } + b.write_string("else{e.error('invalid operands to $op: $ct and \$right.type_name()')}}}") + } + for lt in literal_types { + b.write_string('$lt {match right{') + for ct2 in compound_types { + b.write_string('$ct2{return left${op}right.val}') + } + for lt2 in literal_types { + b.write_string('$lt2{return left${op}right}') + } + b.write_string("else {e.error('invalid operands to $op: ") + b.write_string(if lt == 'i64' { 'int' } else { 'float' }) + b.write_string(" literal and \$right.type_name()')}}}") + } + if op in ['==', '!='] { + b.write_string('string{match right{string{return left${op}right}else{e.error(\'invalid operands to $op: string and \$right.type_name()\')}}}') + } + b.write_string("else {e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}") + } + for math, op in math_ops { + b.write_string('.$math{match left{') + for ct in compound_types { + if op in ['<<', '>>'] && ct == 'Float' { + continue + } + b.write_string('$ct {match right{') + for ct2 in compound_types { + if op in ['<<', '>>'] && ct2 == 'Float' { + continue + } + unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' } + b.write_string('$ct2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left.val)+i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left.val)+u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right.val))$unsafe_end}') + if op !in ['<<', '>>'] { + b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left.val)${op}f64(right.val), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left.val)${op}f64(right.val))}') + } + b.write_string(uk_expect_footer) + } + for lt2 in literal_types { + if op in ['<<', '>>'] && lt2 == 'f64' { + continue + } + unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' } + b.write_string('$lt2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left.val)+i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left.val)+u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right))$unsafe_end}') + if op !in ['<<', '>>'] { + b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left.val)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left.val)${op}f64(right))}') + } + b.write_string(uk_expect_footer) + } + b.write_string("else {e.error('invalid operands to $op: $ct and \$right.type_name()')}}}") + } + for lt in literal_types { + if op in ['<<', '>>'] && lt == 'f64' { + continue + } + b.write_string('$lt{match right{') + for ct2 in compound_types { + if op in ['<<', '>>'] && ct2 == 'Float' { + continue + } + unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' } + b.write_string('$ct2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left)+i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left)+u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right.val))$unsafe_end}') + if op !in ['<<', '>>'] { + b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left)${op}f64(right.val), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left)${op}f64(right.val))}') + } + b.write_string(uk_expect_footer) + } + for lt2 in literal_types { + if op in ['<<', '>>'] && lt2 == 'f64' { + continue + } + unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' } + b.write_string('$lt2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left)+i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left)+u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right))$unsafe_end}') + if op !in ['<<', '>>'] { + b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left)${op}f64(right))}') + } + b.write_string(uk_expect_footer) + } + b.write_string("else {e.error('invalid operands to $op: ") + b.write_string(if lt == 'i64' { 'int' } else { 'float' }) + b.write_string(" literal and \$right.type_name()')}}}") + } + b.write_string("else {e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}") + } + + b.write_string(footer) + + path := @FILE.all_before(@FILE.all_after_last('/')) + '../infix.v' + os.write_file(path, b.str()) or { panic(err) } + res := os.execute(@VEXE + ' fmt -w ' + path) + if res.exit_code != 0 { + eprintln('v fmt failed!') + panic(res.output) + } +} diff --git a/vlib/v/eval/infix.v b/vlib/v/eval/infix.v new file mode 100644 index 0000000000..3240da3fbc --- /dev/null +++ b/vlib/v/eval/infix.v @@ -0,0 +1,2211 @@ +module eval + +import v.token +import v.ast + +fn (e Eval) infix_expr(left Object, right Object, op token.Kind, expecting ast.Type) Object { + match op { + .gt { + match left { + Int { + match right { + Int { return left.val > right.val } + Uint { return left.val > right.val } + Float { return left.val > right.val } + i64 { return left.val > right } + f64 { return left.val > right } + else { e.error('invalid operands to >: Int and $right.type_name()') } + } + } + Uint { + match right { + Int { return left.val > right.val } + Uint { return left.val > right.val } + Float { return left.val > right.val } + i64 { return left.val > right } + f64 { return left.val > right } + else { e.error('invalid operands to >: Uint and $right.type_name()') } + } + } + Float { + match right { + Int { return left.val > right.val } + Uint { return left.val > right.val } + Float { return left.val > right.val } + i64 { return left.val > right } + f64 { return left.val > right } + else { e.error('invalid operands to >: Float and $right.type_name()') } + } + } + i64 { + match right { + Int { return left > right.val } + Uint { return left > right.val } + Float { return left > right.val } + i64 { return left > right } + f64 { return left > right } + else { e.error('invalid operands to >: int literal and $right.type_name()') } + } + } + f64 { + match right { + Int { return left > right.val } + Uint { return left > right.val } + Float { return left > right.val } + i64 { return left > right } + f64 { return left > right } + else { e.error('invalid operands to >: float literal and $right.type_name()') } + } + } + else { + e.error('invalid operands to >: $left.type_name() and $right.type_name()') + } + } + } + .lt { + match left { + Int { + match right { + Int { return left.val < right.val } + Uint { return left.val < right.val } + Float { return left.val < right.val } + i64 { return left.val < right } + f64 { return left.val < right } + else { e.error('invalid operands to <: Int and $right.type_name()') } + } + } + Uint { + match right { + Int { return left.val < right.val } + Uint { return left.val < right.val } + Float { return left.val < right.val } + i64 { return left.val < right } + f64 { return left.val < right } + else { e.error('invalid operands to <: Uint and $right.type_name()') } + } + } + Float { + match right { + Int { return left.val < right.val } + Uint { return left.val < right.val } + Float { return left.val < right.val } + i64 { return left.val < right } + f64 { return left.val < right } + else { e.error('invalid operands to <: Float and $right.type_name()') } + } + } + i64 { + match right { + Int { return left < right.val } + Uint { return left < right.val } + Float { return left < right.val } + i64 { return left < right } + f64 { return left < right } + else { e.error('invalid operands to <: int literal and $right.type_name()') } + } + } + f64 { + match right { + Int { return left < right.val } + Uint { return left < right.val } + Float { return left < right.val } + i64 { return left < right } + f64 { return left < right } + else { e.error('invalid operands to <: float literal and $right.type_name()') } + } + } + else { + e.error('invalid operands to <: $left.type_name() and $right.type_name()') + } + } + } + .eq { + match left { + Int { + match right { + Int { return left.val == right.val } + Uint { return left.val == right.val } + Float { return left.val == right.val } + i64 { return left.val == right } + f64 { return left.val == right } + else { e.error('invalid operands to ==: Int and $right.type_name()') } + } + } + Uint { + match right { + Int { return left.val == right.val } + Uint { return left.val == right.val } + Float { return left.val == right.val } + i64 { return left.val == right } + f64 { return left.val == right } + else { e.error('invalid operands to ==: Uint and $right.type_name()') } + } + } + Float { + match right { + Int { return left.val == right.val } + Uint { return left.val == right.val } + Float { return left.val == right.val } + i64 { return left.val == right } + f64 { return left.val == right } + else { e.error('invalid operands to ==: Float and $right.type_name()') } + } + } + i64 { + match right { + Int { return left == right.val } + Uint { return left == right.val } + Float { return left == right.val } + i64 { return left == right } + f64 { return left == right } + else { e.error('invalid operands to ==: int literal and $right.type_name()') } + } + } + f64 { + match right { + Int { return left == right.val } + Uint { return left == right.val } + Float { return left == right.val } + i64 { return left == right } + f64 { return left == right } + else { e.error('invalid operands to ==: float literal and $right.type_name()') } + } + } + string { + match right { + string { return left == right } + else { e.error('invalid operands to ==: string and $right.type_name()') } + } + } + else { + e.error('invalid operands to ==: $left.type_name() and $right.type_name()') + } + } + } + .ne { + match left { + Int { + match right { + Int { return left.val != right.val } + Uint { return left.val != right.val } + Float { return left.val != right.val } + i64 { return left.val != right } + f64 { return left.val != right } + else { e.error('invalid operands to !=: Int and $right.type_name()') } + } + } + Uint { + match right { + Int { return left.val != right.val } + Uint { return left.val != right.val } + Float { return left.val != right.val } + i64 { return left.val != right } + f64 { return left.val != right } + else { e.error('invalid operands to !=: Uint and $right.type_name()') } + } + } + Float { + match right { + Int { return left.val != right.val } + Uint { return left.val != right.val } + Float { return left.val != right.val } + i64 { return left.val != right } + f64 { return left.val != right } + else { e.error('invalid operands to !=: Float and $right.type_name()') } + } + } + i64 { + match right { + Int { return left != right.val } + Uint { return left != right.val } + Float { return left != right.val } + i64 { return left != right } + f64 { return left != right } + else { e.error('invalid operands to !=: int literal and $right.type_name()') } + } + } + f64 { + match right { + Int { return left != right.val } + Uint { return left != right.val } + Float { return left != right.val } + i64 { return left != right } + f64 { return left != right } + else { e.error('invalid operands to !=: float literal and $right.type_name()') } + } + } + string { + match right { + string { return left != right } + else { e.error('invalid operands to !=: string and $right.type_name()') } + } + } + else { + e.error('invalid operands to !=: $left.type_name() and $right.type_name()') + } + } + } + .plus { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Uint and $right.type_name()') + } + } + } + Float { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Float and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: int literal and $right.type_name()') + } + } + } + f64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: float literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to +: $left.type_name() and $right.type_name()') + } + } + } + .minus { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to *: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to *: Uint and $right.type_name()') + } + } + } + Float { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to *: Float and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to *: int literal and $right.type_name()') + } + } + } + f64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) * i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) * f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) * f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to *: float literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to *: $left.type_name() and $right.type_name()') + } + } + } + .mul { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Uint and $right.type_name()') + } + } + } + Float { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Float and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: int literal and $right.type_name()') + } + } + } + f64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: float literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to +: $left.type_name() and $right.type_name()') + } + } + } + .div { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Uint and $right.type_name()') + } + } + } + Float { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left.val) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left.val) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left.val) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: Float and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: int literal and $right.type_name()') + } + } + } + f64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Float { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right.val)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right.val)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + f64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + return i64(i64(left) + i64(right)) + } else if expecting in ast.float_type_idxs { + return Float{f64(left) + f64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.float_literal_type_idx { + return f64(f64(left) + f64(right)) + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to +: float literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to +: $left.type_name() and $right.type_name()') + } + } + } + .right_shift { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to >>: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) >> i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to >>: Uint and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) >> i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) >> i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to >>: int literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to >>: $left.type_name() and $right.type_name()') + } + } + } + .left_shift { + match left { + Int { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to <<: Int and $right.type_name()') + } + } + } + Uint { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left.val) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left.val) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left.val) << i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to <<: Uint and $right.type_name()') + } + } + } + i64 { + match right { + Int { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + Uint { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right.val), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right.val), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) << i64(right.val)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + i64 { + if expecting in ast.signed_integer_type_idxs { + return Int{i64(left) + i64(right), i8(e.type_to_size(expecting))} + } else if expecting in ast.unsigned_integer_type_idxs { + return Uint{u64(left) + u64(right), i8(e.type_to_size(expecting))} + } else if expecting == ast.int_literal_type_idx { + unsafe { + return i64(i64(left) << i64(right)) + } + } else { + e.error('unknown infix expectation: ${e.table.get_type_symbol(expecting).str()}') + } + } + else { + e.error('invalid operands to <<: int literal and $right.type_name()') + } + } + } + else { + e.error('invalid operands to <<: $left.type_name() and $right.type_name()') + } + } + } + else { + e.error('unknown infix expression: $op') + } + } + return empty // should e.error before this anyway +} diff --git a/vlib/v/eval/object.v b/vlib/v/eval/object.v new file mode 100644 index 0000000000..3373d684b3 --- /dev/null +++ b/vlib/v/eval/object.v @@ -0,0 +1,150 @@ +module eval + +const empty = Void{} + +// NB: i64 is an int_literal, NOT an i64 (same with f64) +type Object = Array + | Float + | Int + | Ptr + | Uint + | Void + | []Object + | bool + | byte + | char + | f64 + | i64 + | rune + | string + | voidptr + +// string is the same as the autogenerated str() methods +pub fn (o Object) string() string { + match o { + byte { + panic('error: byte should only be used for &byte') + } + bool { + return o.str() + } + i64 { // int_literal + return o.str() + } + f64 { // float_literal + return o.str() + } + Int { + return o.val.str() + } + Uint { + return o.val.str() + } + Float { + return o.val.str() + } + string { + return o + } + Void { + return '' + } + []Object { + mut res := '(' + for i, obj in o { + res += obj.str() + if i + 1 != o.len { + res += ', ' + } + } + return res + ')' + } + voidptr { + return o.str() + } + char { + return int(o).str() + } + rune { + return o.str() + } + Array { + mut res := '[' + for i, val in o.val { + res += val.string() + if i + 1 != o.val.len { + res += ', ' + } + } + return res + ']' + } + Ptr { + return o.val.str() + } + } +} + +pub fn (o Object) int_val() i64 { + match o { + Int { + return o.val + } + Uint { + return i64(o.val) + } + i64 { + return o + } + else { + panic('Object.int_val(): not an int') + } + } +} + +pub fn (o Object) float_val() f64 { + match o { + Float { + return o.val + } + f64 { + return o + } + else { + panic('Object.float_val(): not a float') + } + } +} + +struct Void {} + +pub struct Int { +pub mut: + val i64 + size i8 // 8/16/32/64 +} + +pub struct Uint { +pub mut: + val u64 + size i8 // 8/16/32/64 +} + +pub struct Float { +pub mut: + val f64 + size i8 // 8/16/32/64 +} + +pub struct Array { +pub mut: + val []Object +} + +pub struct Ptr { + val &Object +} + +// override the autogenerated str, since it does not work +fn (p Ptr) str() string { + return u64(p.val).str() +} diff --git a/vlib/v/eval/stmt.v b/vlib/v/eval/stmt.v new file mode 100644 index 0000000000..e0781abfb5 --- /dev/null +++ b/vlib/v/eval/stmt.v @@ -0,0 +1,93 @@ +module eval + +import v.ast + +pub fn (mut e Eval) stmts(stmts []ast.Stmt) { + e.open_scope() + for stmt in stmts { + e.stmt(stmt) + if e.returning { + break + } + } + e.close_scope() +} + +pub fn (mut e Eval) stmt(stmt ast.Stmt) { + match stmt { + ast.ExprStmt { + e.expr(stmt.expr, stmt.typ) + } + ast.AssignStmt { + // if stmt.left.len != 1 { + // e.error('multiple values assignments are not supported') + // } + mut rights := []Object{} + for i, right in stmt.right { + rights << e.expr(right, stmt.right_types[i]) + } + if rights[0] is []Object { // needs to be unpacked + e.error('multiple assignment from function is not supported') + } + match stmt.op { + .decl_assign { + for i, left in stmt.left { + e.set(left, rights[i], true, stmt.left_types[i]) + } + } + .assign { + for i, left in stmt.left { + e.set(left, rights[i], false, stmt.left_types[i]) + } + } + else { + e.error('unknown assign statment: $stmt.op') + } + } + } + ast.Return { + e.returning = true + e.return_values = [] + for i, expr in stmt.exprs { + e.return_values << e.expr(expr, stmt.types[i]) + } + } + ast.ForInStmt { + if !stmt.is_range { + e.error('only range for in statements are supported') + } + if stmt.key_var != '' { + e.error('keys are not supported in for in statements') + } + e.open_scope() + underscore := stmt.val_var == '_' + if !underscore { + e.set(ast.Ident{ name: stmt.val_var, scope: 0 }, Int{-1, 32}, true, stmt.val_type) + } + for i in (e.expr(stmt.cond, ast.int_type_idx) as Int).val .. (e.expr(stmt.high, + ast.int_type_idx) as Int).val { + if !underscore { + e.set(ast.Ident{ name: stmt.val_var, scope: 0 }, Int{i, 32}, false, + stmt.val_type) + } + e.stmts(stmt.stmts) + } + e.close_scope() + } + ast.ForStmt { + for { + should_break := e.expr(stmt.cond, ast.bool_type_idx) + if !(should_break as bool) { + break + } + e.stmts(stmt.stmts) + } + } + ast.Block { + e.stmts(stmt.stmts) + } + else { + e.error('unhandled statement $stmt.type_name()') + } + } +} diff --git a/vlib/v/eval/var.v b/vlib/v/eval/var.v new file mode 100644 index 0000000000..70226619ec --- /dev/null +++ b/vlib/v/eval/var.v @@ -0,0 +1,68 @@ +module eval + +import v.ast + +pub struct Var { +pub mut: + val Object +pub: + scope_idx int + typ ast.Type +} + +pub fn (mut e Eval) open_scope() { + e.scope_idx++ +} + +pub fn (mut e Eval) close_scope() { + e.scope_idx-- + for name, var in e.local_vars { + if var.scope_idx > e.scope_idx { + e.local_vars.delete(name) + } + } +} + +pub fn (mut e Eval) set(expr ast.Expr, val Object, init bool, typ ast.Type) { + match expr { + ast.Ident { + if init { + e.local_vars[expr.name] = Var{ + val: val + scope_idx: e.scope_idx + typ: typ + } + } else { + e.local_vars[expr.name].val = val + } + } + ast.IndexExpr { + panic('>>$expr.pos, $e.cur_file') + + // if init { + // e.error('index init assignment') + // } else { + // mut x := (e.local_vars[(expr.left as ast.Ident).name].val) + // if x is Array { + // x.val[(e.expr(expr.index, ast.int_type_idx) as Int).val] = val + // } + // } + } + else { + panic('unknown left value to assign statment: $expr.type_name()') + } + } +} + +// val and expr must be both numeric types, or both string +pub fn (mut e Eval) add(expr ast.Expr, val Object) { + match expr { + ast.Ident { + e.local_vars[expr.name].val = e.infix_expr(e.local_vars[expr.name].val, val, + .plus, e.local_vars[expr.name].typ) + } + else { + panic('unknown left value to add statment: $expr.type_name()') + } + } +} diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index 80c2977573..b54f948b51 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -49,17 +49,15 @@ pub enum Backend { js_browser // The JavaScript browser backend js_freestanding // The JavaScript freestanding backend native // The Native backend + interpret // Interpret the ast } pub fn (b Backend) is_js() bool { - match b { - .js_node, .js_browser, .js_freestanding { - return true - } - else { - return false - } - } + return b in [ + .js_node, + .js_browser, + .js_freestanding, + ] } pub enum CompilerType { @@ -486,6 +484,9 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences res.backend = .native res.build_options << arg } + '-interpret' { + res.backend = .interpret + } '-W' { res.warns_are_errors = true } @@ -707,6 +708,21 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences res.is_run = true res.path = command res.run_args = args[command_pos + 1..] + } else if command == 'interpret' { + res.backend = .interpret + if command_pos + 2 > args.len { + eprintln('v interpret: no v files listed') + exit(1) + } + res.path = args[command_pos + 1] + res.run_args = args[command_pos + 2..] + + must_exist(res.path) + if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) + && os.is_file(res.path + '.v') { + eprintln('It looks like you wanted to run "${res.path}.v", so we went ahead and did that since "$res.path" is an executable.') + res.path += '.v' + } } if command == 'build-module' { res.build_mode = .build_module @@ -801,6 +817,7 @@ pub fn backend_from_string(s string) ?Backend { 'js_browser' { return .js_browser } 'js_freestanding' { return .js_freestanding } 'native' { return .native } + 'interpret' { return .interpret } else { return error('Unknown backend type $s') } } } diff --git a/vlib/v/pref/should_compile.v b/vlib/v/pref/should_compile.v index 09cc1ce0cf..ffb116bb01 100644 --- a/vlib/v/pref/should_compile.v +++ b/vlib/v/pref/should_compile.v @@ -15,7 +15,7 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s || file.all_before_last('.v').all_before_last('.').ends_with('_test') { continue } - if prefs.backend == .c && !prefs.should_compile_c(file) { + if prefs.backend in [.c, .interpret] && !prefs.should_compile_c(file) { continue } if prefs.backend.is_js() && !prefs.should_compile_js(file) {