[vm] procedure call parsing / fake procedure calls

This commit is contained in:
Judah Caruso 2025-06-03 11:39:00 -06:00
parent 93e59df676
commit dc04c0463b
3 changed files with 86 additions and 1 deletions

View file

@ -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 == {

View file

@ -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);

View file

@ -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;