improvements
This commit is contained in:
parent
3bfa0679ae
commit
3f81359ab1
3 changed files with 105 additions and 21 deletions
|
|
@ -20,6 +20,7 @@ Interp_Value :: struct {
|
|||
s: string;
|
||||
p: *void;
|
||||
proc: *Node_Procedure;
|
||||
val: *Interp_Value;
|
||||
}
|
||||
|
||||
Kind :: enum {
|
||||
|
|
@ -31,6 +32,7 @@ Interp_Value :: struct {
|
|||
string;
|
||||
pointer;
|
||||
procedure;
|
||||
value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,24 +49,44 @@ init :: (i: *Interp, allocator: Allocator) {
|
|||
}
|
||||
|
||||
interp_program :: (i: *Interp) {
|
||||
scope := i.global;
|
||||
for i.toplevel {
|
||||
interp_statement(i, it, i.global);
|
||||
}
|
||||
}
|
||||
|
||||
for i.toplevel if it.kind == {
|
||||
interp_statement :: (i: *Interp, stmt: *Node, scope: *Interp_Scope) {
|
||||
if stmt.kind == {
|
||||
case .variable;
|
||||
var := it.(*Node_Var);
|
||||
var := stmt.(*Node_Var);
|
||||
sym := var.symbol;
|
||||
basic.assert(!kv.exists(*scope.bindings, sym.str), "redeclaring symbol '%'", sym.str); // @errors
|
||||
|
||||
value := value_nil;
|
||||
if var.value_expr != null {
|
||||
value = interp_expr(i, var.value_expr, i.global);
|
||||
value = interp_expr(i, var.value_expr, scope);
|
||||
basic.assert(value != null); // @errors
|
||||
}
|
||||
|
||||
kv.set(*scope.bindings, sym.str, value);
|
||||
|
||||
case .assign;
|
||||
assign := stmt.(*Node_Assign);
|
||||
|
||||
src := interp_expr(i, assign.src, scope);
|
||||
basic.assert(src != null); // @errors
|
||||
|
||||
dst := interp_lvalue(i, assign.dst, scope);
|
||||
basic.assert(dst != null); // @errors
|
||||
basic.assert(dst.kind == .value); // @errors
|
||||
|
||||
// @todo: typechecking
|
||||
if assign.op.kind == {
|
||||
case .equal;
|
||||
dst.val.* = src.*;
|
||||
}
|
||||
|
||||
case .procedure;
|
||||
proc := it.(*Node_Procedure);
|
||||
proc := stmt.(*Node_Procedure);
|
||||
sym := proc.symbol;
|
||||
basic.assert(!kv.exists(*scope.bindings, sym.str), "redeclaring procedure '%'", sym.str);
|
||||
|
||||
|
|
@ -73,9 +95,9 @@ interp_program :: (i: *Interp) {
|
|||
kv.set(*scope.bindings, sym.str, value);
|
||||
|
||||
case .print;
|
||||
print := it.(*Node_Print);
|
||||
expr := interp_expr(i, print.expr, i.global);
|
||||
if expr == null continue;
|
||||
print := stmt.(*Node_Print);
|
||||
expr := interp_expr(i, print.expr, scope);
|
||||
if expr == null return;
|
||||
|
||||
if expr.kind == {
|
||||
case .none; // do nothing
|
||||
|
|
@ -90,10 +112,27 @@ interp_program :: (i: *Interp) {
|
|||
basic.print("\n");
|
||||
|
||||
case;
|
||||
basic.assert(false, "unhandled node kind: %", it.kind); // @errors
|
||||
interp_expr(i, stmt, scope);
|
||||
// basic.assert(false, "unhandled node kind: %", stmt.kind); // @errors
|
||||
}
|
||||
}
|
||||
|
||||
interp_lvalue :: (i: *Interp, expr: *Node, scope: *Interp_Scope) -> *Interp_Value {
|
||||
if expr.kind == {
|
||||
case .symbol;
|
||||
sym := expr.(*Node_Symbol);
|
||||
lval := find_symbol(scope, sym.str);
|
||||
oval := make_interp_value(i, .value);
|
||||
oval.val = lval;
|
||||
return oval;
|
||||
|
||||
case;
|
||||
basic.assert(false, "unable to get lvalue from %", expr.kind);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
interp_expr :: (i: *Interp, expr: *Node, scope: *Interp_Scope) -> *Interp_Value {
|
||||
if expr.kind == {
|
||||
case .procedure_call;
|
||||
|
|
@ -102,7 +141,7 @@ interp_expr :: (i: *Interp, expr: *Node, scope: *Interp_Scope) -> *Interp_Value
|
|||
|
||||
// @temp
|
||||
sym := call.call_expr.(*Node_Symbol);
|
||||
basic.assert(sym.kind == .symbol);
|
||||
basic.assert(sym.kind == .symbol, "%", sym.kind);
|
||||
|
||||
value := find_symbol(scope, sym.str);
|
||||
basic.assert(value != null, "procedure didn't exists '%'", sym.str);
|
||||
|
|
@ -126,6 +165,9 @@ interp_expr :: (i: *Interp, expr: *Node, scope: *Interp_Scope) -> *Interp_Value
|
|||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
interp_statement(i, expr, proc_scope);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ strings :: #import "String"; // @future
|
|||
init(*parser, context.allocator);
|
||||
|
||||
ok := parse_string(*parser, #string END
|
||||
fn add(x, y) do return x + y end
|
||||
fn add(a, b) do return a + b end
|
||||
fn sub(x, y) do return x - y end
|
||||
|
||||
var x = 11.0
|
||||
var y = 22.0
|
||||
|
||||
print add(x, y)
|
||||
print add(x+1.0, y)
|
||||
add(1.0, 1.0)
|
||||
// print add(x+1.0, y)
|
||||
END);
|
||||
|
||||
interp: Interp;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ Node :: struct {
|
|||
stmt_start;
|
||||
print;
|
||||
return_;
|
||||
assign;
|
||||
stmt_end;
|
||||
|
||||
decl_start;
|
||||
|
|
@ -99,6 +100,15 @@ Node_Var :: struct {
|
|||
}
|
||||
}
|
||||
|
||||
Node_Assign :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .assign;
|
||||
|
||||
op: Token;
|
||||
dst: *Node;
|
||||
src: *Node;
|
||||
}
|
||||
|
||||
Node_Unary :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .unary;
|
||||
|
|
@ -256,7 +266,7 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
|||
break;
|
||||
}
|
||||
|
||||
node := parse_toplevel(p);
|
||||
node := parse_statement(p);
|
||||
if node != null array.append(*p.toplevel, node);
|
||||
}
|
||||
|
||||
|
|
@ -266,17 +276,17 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
|||
|
||||
#scope_file;
|
||||
|
||||
parse_toplevel :: (p: *Parser) -> *Node {
|
||||
t, ok := expect_token(p, .kw_var, .kw_def, .kw_fn, .kw_print, .kw_do, .kw_return);
|
||||
basic.assert(ok, "var, def, print, found '%'", t.str); // @errors
|
||||
|
||||
parse_statement :: (p: *Parser) -> *Node {
|
||||
t := peek_token(p);
|
||||
if t.kind == {
|
||||
// var sym type_expr
|
||||
// var sym type_expr = expr
|
||||
// var sym = expr
|
||||
case .kw_var; #through;
|
||||
case .kw_def;
|
||||
s:, ok = expect_token(p, .symbol);
|
||||
consume_token(p);
|
||||
|
||||
s, ok := expect_token(p, .symbol);
|
||||
basic.assert(ok, "symbol"); // @errors
|
||||
|
||||
type_expr: *Node_Type;
|
||||
|
|
@ -317,6 +327,8 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
// return
|
||||
// return expr0, ..exprN
|
||||
case .kw_return;
|
||||
consume_token(p);
|
||||
|
||||
node := make_node(p, Node_Return);
|
||||
|
||||
prev_offset := p.offset;
|
||||
|
|
@ -332,6 +344,8 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
// print(expr)
|
||||
// print expr
|
||||
case .kw_print;
|
||||
consume_token(p);
|
||||
|
||||
expr := parse_expression(p);
|
||||
basic.assert(expr != null, "expected expression"); // @errors
|
||||
|
||||
|
|
@ -341,6 +355,8 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
|
||||
// fn symbol(arg0, ..argN) do ... end
|
||||
case .kw_fn;
|
||||
consume_token(p);
|
||||
|
||||
symbol, ok := expect_token(p, .symbol);
|
||||
basic.assert(ok, "expected name for procedure"); // @errors @todo(judah): lambdas
|
||||
|
||||
|
|
@ -381,9 +397,35 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
basic.assert(node.block != null, "expected block"); // @errors
|
||||
|
||||
return node;
|
||||
|
||||
// do ... end
|
||||
case .kw_do;
|
||||
return parse_block(p);
|
||||
}
|
||||
|
||||
return null;
|
||||
return parse_simple_statement(p);
|
||||
}
|
||||
|
||||
parse_simple_statement :: (p: *Parser) -> *Node {
|
||||
dst := parse_expression(p);
|
||||
basic.assert(dst != null, "expected expression for simple statement");
|
||||
|
||||
t := peek_token(p);
|
||||
if t.kind == {
|
||||
case .equal;
|
||||
consume_token(p);
|
||||
|
||||
src := parse_expression(p);
|
||||
basic.assert(src != null, "expected right-hand side of assignment");
|
||||
|
||||
node := make_node(p, Node_Assign);
|
||||
node.op = t;
|
||||
node.dst = dst;
|
||||
node.src = src;
|
||||
return node;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
parse_block :: (p: *Parser) -> *Node_Block {
|
||||
|
|
@ -396,7 +438,7 @@ parse_block :: (p: *Parser) -> *Node_Block {
|
|||
t = peek_token(p);
|
||||
if t.kind == .kw_end break;
|
||||
|
||||
node := parse_toplevel(p);
|
||||
node := parse_statement(p);
|
||||
basic.assert(node != null); // @errors
|
||||
|
||||
array.append(*block.body, node);
|
||||
|
|
|
|||
Loading…
Reference in a new issue