[vm] procedure call parsing / fake procedure calls
This commit is contained in:
parent
93e59df676
commit
dc04c0463b
3 changed files with 86 additions and 1 deletions
|
|
@ -74,6 +74,26 @@ interp_program :: (i: *Interp) {
|
||||||
|
|
||||||
interp_expr :: (i: *Interp, expr: *Node) -> *Interp_Value {
|
interp_expr :: (i: *Interp, expr: *Node) -> *Interp_Value {
|
||||||
if expr.kind == {
|
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;
|
case .unary;
|
||||||
do_unop :: (code: Code) #expand {
|
do_unop :: (code: Code) #expand {
|
||||||
if rhs.kind == {
|
if rhs.kind == {
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,12 @@ strings :: #import "String"; // @future
|
||||||
var x = 10.0
|
var x = 10.0
|
||||||
var y = 20.0
|
var y = 20.0
|
||||||
var z = x + y * 2.0 / 3.0
|
var z = x + y * 2.0 / 3.0
|
||||||
|
var w = add(x, y)
|
||||||
|
|
||||||
print x // 10
|
print x // 10
|
||||||
print y // 20
|
print y // 20
|
||||||
print z // 23.3
|
print z // 23.3
|
||||||
|
print w // 30
|
||||||
// print z
|
// print z
|
||||||
END);
|
END);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ Node :: struct {
|
||||||
type;
|
type;
|
||||||
unary;
|
unary;
|
||||||
binary;
|
binary;
|
||||||
|
procedure_call;
|
||||||
symbol;
|
symbol;
|
||||||
literal;
|
literal;
|
||||||
expr_end;
|
expr_end;
|
||||||
|
|
@ -86,6 +87,15 @@ Node_Print :: struct {
|
||||||
expr: *Node;
|
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 {
|
Node_Var :: struct {
|
||||||
#as using n: Node;
|
#as using n: Node;
|
||||||
n.kind = .variable;
|
n.kind = .variable;
|
||||||
|
|
@ -221,7 +231,6 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
||||||
// var sym = expr
|
// var sym = expr
|
||||||
case .kw_var; #through;
|
case .kw_var; #through;
|
||||||
case .kw_def;
|
case .kw_def;
|
||||||
|
|
||||||
s:, ok = expect_token(p, .symbol);
|
s:, ok = expect_token(p, .symbol);
|
||||||
basic.assert(ok, "symbol"); // @errors
|
basic.assert(ok, "symbol"); // @errors
|
||||||
|
|
||||||
|
|
@ -403,6 +412,56 @@ parse_expression_postfix :: (p: *Parser) -> *Node {
|
||||||
// @TODO
|
// @TODO
|
||||||
base := parse_expression_base(p);
|
base := parse_expression_base(p);
|
||||||
basic.assert(base != null, "expected expression"); // @errors
|
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;
|
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;
|
||||||
case "("; #through;
|
case "("; #through;
|
||||||
case ")"; #through;
|
case ")"; #through;
|
||||||
case "["; #through;
|
case "["; #through;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue