diff --git a/vm/interp.jai b/vm/interp.jai index 648ad2e..ce755fc 100644 --- a/vm/interp.jai +++ b/vm/interp.jai @@ -74,6 +74,26 @@ interp_program :: (i: *Interp) { interp_expr :: (i: *Interp, expr: *Node) -> *Interp_Value { if expr.kind == { + case .procedure_call; + call := expr.(*Node_Procedure_Call); + args := call.all_arguments; + + // @temp + sym := call.call_expr.(*Node_Symbol); + basic.assert(sym.kind == .symbol); + if sym.str == { + case "add"; + basic.assert(args.count == 2, "mismatched number of arguments; require 2, given %", args.count); // @errors + + node := mem.request_memory(Node_Binary,, allocator = basic.temp); + node.op = .{ kind = .plus, str = "+" }; + node.left = args[0]; + node.right = args[1]; + return interp_expr(i, node); + } + + return value_nil; + case .unary; do_unop :: (code: Code) #expand { if rhs.kind == { diff --git a/vm/module.jai b/vm/module.jai index fb4297b..267b041 100644 --- a/vm/module.jai +++ b/vm/module.jai @@ -24,10 +24,12 @@ strings :: #import "String"; // @future var x = 10.0 var y = 20.0 var z = x + y * 2.0 / 3.0 + var w = add(x, y) print x // 10 print y // 20 print z // 23.3 + print w // 30 // print z END); diff --git a/vm/parser.jai b/vm/parser.jai index 1a92a2a..98f11a3 100644 --- a/vm/parser.jai +++ b/vm/parser.jai @@ -73,6 +73,7 @@ Node :: struct { type; unary; binary; + procedure_call; symbol; literal; expr_end; @@ -86,6 +87,15 @@ Node_Print :: struct { expr: *Node; } +Node_Procedure_Call :: struct { + #as using n: Node; + n.kind = .procedure_call; + + call_expr: *Node; + named_arguments: kv.Kv(*Node, *Node); + all_arguments: [..]*Node; +} + Node_Var :: struct { #as using n: Node; n.kind = .variable; @@ -221,7 +231,6 @@ parse_toplevel :: (p: *Parser) -> *Node { // var sym = expr case .kw_var; #through; case .kw_def; - s:, ok = expect_token(p, .symbol); basic.assert(ok, "symbol"); // @errors @@ -403,6 +412,56 @@ parse_expression_postfix :: (p: *Parser) -> *Node { // @TODO base := parse_expression_base(p); basic.assert(base != null, "expected expression"); // @errors + + t := peek_token(p); + if t.kind == { + case .l_paren; // procedure calls + consume_token(p); + + node := make_node(p, Node_Procedure_Call); + node.call_expr = base; + + array.init(*node.all_arguments, p.allocator); + kv.init(*node.named_arguments, p.allocator); + + while !at_end(p) { + t = peek_token(p); + if t.kind == .r_paren break; + + arg_or_name := parse_expression(p); + basic.assert(arg_or_name != null, "expected expression in procedure call"); // @errors + + if peek_token(p).kind == .colon { + consume_token(p); + basic.assert(arg_or_name.kind == .symbol, "expected symbol for named argument"); // @errors + basic.assert(!kv.exists(*node.named_arguments, arg_or_name), "duplicate named argument '%'", arg_or_name.(*Node_Symbol).str); // @errors + + value := parse_expression(p); + basic.assert(value != null, "expected expression after ':'"); // @errors + array.append(*node.all_arguments, value); + kv.set(*node.named_arguments, arg_or_name, value); + } + else { + array.append(*node.all_arguments, arg_or_name); + } + + t = peek_token(p); + if t.kind == { + case .comma; + consume_token(p); + continue; + case .r_paren; + break; + case; + basic.assert(false, "expected ',' or ')' but found '%'", t.str); + } + } + + _, ok := expect_token(p, .r_paren); + basic.assert(ok, "expected ')'"); // @errors + return node; + } + return base; } @@ -581,6 +640,10 @@ consume_token :: (p: *Parser) -> Token { case "%"; #through; case "!"; #through; case "&"; #through; + case ","; #through; + case "."; #through; + case ":"; #through; + case ";"; #through; case "("; #through; case ")"; #through; case "["; #through;