[vm] more procedure things
This commit is contained in:
parent
7e685785be
commit
b1a9e84d8b
3 changed files with 101 additions and 51 deletions
|
|
@ -13,6 +13,8 @@ Interp_Value :: struct {
|
|||
u: u64;
|
||||
f: float64;
|
||||
s: string;
|
||||
p: *void;
|
||||
proc: *Node_Procedure;
|
||||
}
|
||||
|
||||
Kind :: enum {
|
||||
|
|
@ -22,6 +24,8 @@ Interp_Value :: struct {
|
|||
int;
|
||||
float;
|
||||
string;
|
||||
pointer;
|
||||
procedure;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +43,7 @@ interp_program :: (i: *Interp) {
|
|||
for i.toplevel if it.kind == {
|
||||
case .variable;
|
||||
var := it.(*Node_Var);
|
||||
sym := var.symbol.(*Node_Symbol);
|
||||
sym := var.symbol;
|
||||
basic.assert(!kv.exists(*i.symbols, sym.str), "redeclaring symbol '%'", sym.str); // @errors
|
||||
|
||||
value := value_nil;
|
||||
|
|
@ -50,6 +54,15 @@ interp_program :: (i: *Interp) {
|
|||
|
||||
kv.set(*i.symbols, sym.str, value);
|
||||
|
||||
case .procedure;
|
||||
proc := it.(*Node_Procedure);
|
||||
sym := proc.symbol;
|
||||
basic.assert(!kv.exists(*i.symbols, sym.str), "redeclaring procedure '%'", sym.str);
|
||||
|
||||
value := make_interp_value(i, .procedure);
|
||||
value.proc = proc;
|
||||
kv.set(*i.symbols, sym.str, value);
|
||||
|
||||
case .print;
|
||||
print := it.(*Node_Print);
|
||||
expr := interp_expr(i, print.expr);
|
||||
|
|
@ -81,18 +94,27 @@ interp_expr :: (i: *Interp, expr: *Node) -> *Interp_Value {
|
|||
// @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);
|
||||
value, ok := kv.get(*i.symbols, sym.str);
|
||||
basic.assert(ok, "procedure didn't exists '%'", sym.str);
|
||||
basic.assert(value.kind == .procedure, "attempt to call non procedure '%'", sym.str);
|
||||
|
||||
result := value_nil;
|
||||
proc := value.proc;
|
||||
|
||||
// @todo(judah): check arity, create scope, map args to locals, exec
|
||||
for expr: proc.block.body {
|
||||
if expr.kind == .return_ {
|
||||
ret := expr.(*Node_Return);
|
||||
if ret.values.count != 0 {
|
||||
result = interp_expr(i, ret.values[0]);
|
||||
}
|
||||
|
||||
return value_nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
case .unary;
|
||||
do_unop :: (code: Code) #expand {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ strings :: #import "String"; // @future
|
|||
fn add(x, y) do return x + y end
|
||||
fn sub(x, y) do return x - y end
|
||||
|
||||
var x = 10.0
|
||||
var y = 20.0
|
||||
var x = 11.0
|
||||
var y = 22.0
|
||||
var z = x + y * 2.0 / 3.0
|
||||
var w = add(x, y)
|
||||
|
||||
|
|
|
|||
100
vm/parser.jai
100
vm/parser.jai
|
|
@ -89,8 +89,8 @@ Node_Var :: struct {
|
|||
#as using n: Node;
|
||||
n.kind = .variable;
|
||||
|
||||
symbol: *Node; // always *Node_Symbol
|
||||
type_expr: *Node; // always *Node_Type
|
||||
symbol: *Node_Symbol;
|
||||
type_expr: *Node_Type;
|
||||
value_expr: *Node;
|
||||
var_flags: Var_Flag;
|
||||
|
||||
|
|
@ -158,18 +158,23 @@ Node_Type :: struct {
|
|||
type_kind: Type_Kind;
|
||||
|
||||
union {
|
||||
alias_target: *Node;
|
||||
name_target: *Node_Symbol;
|
||||
pointer_target: *Node_Type;
|
||||
struct {
|
||||
array_element: *Node_Type;
|
||||
array_count: *Node; // can be null
|
||||
};
|
||||
struct {
|
||||
procedure_arguments: [..]*Node_Type;
|
||||
procedure_returns: [..]*Node_Type;
|
||||
};
|
||||
}
|
||||
|
||||
Type_Kind :: enum {
|
||||
alias;
|
||||
named;
|
||||
pointer;
|
||||
array;
|
||||
procedure;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,11 +182,12 @@ Node_Procedure :: struct {
|
|||
#as using n: Node;
|
||||
n.kind = .procedure;
|
||||
|
||||
header: *Node_Procedure_Header;
|
||||
arguments: [..]Parameter;
|
||||
returns: [..]Parameter;
|
||||
|
||||
args: [..]Node_Parameter;
|
||||
rets: [..]Node_Parameter;
|
||||
body: *Node_Block;
|
||||
symbol: *Node_Symbol; // can be null
|
||||
head: *Node_Type; // will always be of type .procedure
|
||||
block: *Node_Block;
|
||||
flags: Flag;
|
||||
|
||||
Flag :: enum_flags {
|
||||
|
|
@ -189,17 +195,12 @@ Node_Procedure :: struct {
|
|||
}
|
||||
}
|
||||
|
||||
Node_Parameter :: struct {
|
||||
Parameter :: struct {
|
||||
symbol: *Node_Symbol;
|
||||
type: *Node_Type;
|
||||
value: *Node; // always an expression, can be null
|
||||
}
|
||||
|
||||
Node_Procedure_Header :: struct {
|
||||
args: [..]*Node_Type;
|
||||
rets: [..]*Node_Type;
|
||||
}
|
||||
|
||||
Node_Print :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .print;
|
||||
|
|
@ -219,6 +220,7 @@ Node_Procedure_Call :: struct {
|
|||
Node_Block :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .block;
|
||||
|
||||
body: [..]*Node;
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +279,7 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
s:, ok = expect_token(p, .symbol);
|
||||
basic.assert(ok, "symbol"); // @errors
|
||||
|
||||
type_expr: *Node;
|
||||
type_expr: *Node_Type;
|
||||
value_expr: *Node;
|
||||
is_const := t.kind == .kw_def;
|
||||
|
||||
|
|
@ -316,7 +318,6 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
// return expr0, ..exprN
|
||||
case .kw_return;
|
||||
node := make_node(p, Node_Return);
|
||||
array.init(*node.values, p.allocator);
|
||||
|
||||
prev_offset := p.offset;
|
||||
expr := parse_expression(p);
|
||||
|
|
@ -338,7 +339,7 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
node.expr = expr;
|
||||
return node;
|
||||
|
||||
// fn symbol(arg0, ..argN) do end
|
||||
// fn symbol(arg0, ..argN) do ... end
|
||||
case .kw_fn;
|
||||
symbol, ok := expect_token(p, .symbol);
|
||||
basic.assert(ok, "expected name for procedure"); // @errors @todo(judah): lambdas
|
||||
|
|
@ -346,12 +347,20 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
t, ok = expect_token(p, .l_paren);
|
||||
basic.assert(ok, "expected '(' but found '%'", t.str); // @errors
|
||||
|
||||
node := make_node(p, Node_Procedure);
|
||||
node.symbol = make_node(p, Node_Symbol);
|
||||
node.symbol.str = symbol.str;
|
||||
|
||||
while !at_end(p) {
|
||||
t = peek_token(p);
|
||||
if t.kind == .r_paren break;
|
||||
|
||||
expr := parse_expression(p);
|
||||
basic.assert(expr != null); // @errors
|
||||
sym, ok := expect_token(p, .symbol);
|
||||
basic.assert(ok, "expected symbol"); // @errors
|
||||
|
||||
arg := array.append(*node.arguments);
|
||||
arg.symbol = make_node(p, Node_Symbol);
|
||||
arg.symbol.str = sym.str;
|
||||
|
||||
t = peek_token(p);
|
||||
if t.kind == {
|
||||
|
|
@ -368,12 +377,10 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
_, ok = expect_token(p, .r_paren);
|
||||
basic.assert(ok, "expected ')'"); // @errors
|
||||
|
||||
block := parse_block(p);
|
||||
basic.assert(block != null, "expected block"); // @errors
|
||||
node.block = parse_block(p);
|
||||
basic.assert(node.block != null, "expected block"); // @errors
|
||||
|
||||
node := make_node(p, Node_Procedure);
|
||||
|
||||
return null;
|
||||
return node;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -384,7 +391,6 @@ parse_block :: (p: *Parser) -> *Node_Block {
|
|||
basic.assert(ok, "expected 'do' found '%'", t.str); // @errors
|
||||
|
||||
block := make_node(p, Node_Block);
|
||||
array.init(*block.body, p.allocator);
|
||||
|
||||
while !at_end(p) {
|
||||
t = peek_token(p);
|
||||
|
|
@ -411,14 +417,12 @@ parse_type_expression :: (p: *Parser) -> *Node_Type {
|
|||
target := parse_type_expression(p);
|
||||
basic.assert(target != null, "pointer target"); // @errors
|
||||
|
||||
node := make_node(p, Node_Type);
|
||||
node.type_kind = .pointer;
|
||||
node := make_node(p, .pointer);
|
||||
node.pointer_target = target;
|
||||
return node;
|
||||
|
||||
case .l_square;
|
||||
node := make_node(p, Node_Type);
|
||||
node.type_kind = .array;
|
||||
node := make_node(p, .array);
|
||||
|
||||
// slice
|
||||
if peek_token(p).kind == .r_square {
|
||||
|
|
@ -449,9 +453,8 @@ parse_type_expression :: (p: *Parser) -> *Node_Type {
|
|||
symbol := make_node(p, Node_Symbol);
|
||||
symbol.str = t.str;
|
||||
|
||||
node := make_node(p, Node_Type);
|
||||
node.type_kind = .alias;
|
||||
node.alias_target = symbol;
|
||||
node := make_node(p, .named);
|
||||
node.name_target = symbol;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
@ -540,9 +543,6 @@ parse_expression_postfix :: (p: *Parser) -> *Node {
|
|||
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;
|
||||
|
|
@ -641,7 +641,35 @@ parse_expression_base :: (p: *Parser) -> *Node {
|
|||
}
|
||||
|
||||
make_node :: (p: *Parser, $T: Type) -> *T {
|
||||
return mem.request_memory(T,, allocator = p.allocator);
|
||||
node := mem.request_memory(T,, allocator = p.allocator);
|
||||
|
||||
#if T == { // nodes that require initialization
|
||||
case Node_Block;
|
||||
array.init(*node.body, p.allocator);
|
||||
case Node_Return;
|
||||
array.init(*node.values, p.allocator);
|
||||
case Node_Procedure_Call;
|
||||
array.init(*node.all_arguments, p.allocator);
|
||||
kv.init(*node.named_arguments, p.allocator);
|
||||
case Node_Procedure;
|
||||
array.init(*node.arguments, p.allocator);
|
||||
array.init(*node.returns, p.allocator);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
make_node :: (p: *Parser, $type_kind: Node_Type.Type_Kind) -> *Node_Type {
|
||||
type := mem.request_memory(Node_Type,, allocator = p.allocator);
|
||||
type.type_kind = type_kind;
|
||||
|
||||
#if type_kind == {
|
||||
case .procedure;
|
||||
array.init(*type.procedure_arguments, p.allocator);
|
||||
array.init(*type.procedure_returns, p.allocator);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
peek_token :: (p: *Parser) -> Token {
|
||||
|
|
|
|||
Loading…
Reference in a new issue