From 9e55cdb1ea5cd8318a1a0b7a9f64f09e8d8ad692 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 31 Oct 2019 17:10:36 -0400 Subject: a.b as an lvalue --- eval.c | 22 +++++++++++++++++++--- main.c | 1 - parse.c | 2 +- test.toc | 28 +++++++++------------------- toc.c | 8 ++++++++ types.c | 8 ++++---- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/eval.c b/eval.c index ff92ea9..ed88c2c 100644 --- a/eval.c +++ b/eval.c @@ -682,7 +682,15 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { /* set it to to */ eval_deref_set(ptr, to, type); } break; - default: break; + case BINARY_DOT: { + Value struc; + if (!eval_expr(ev, set->binary.lhs, &struc)) + return false; + eval_struct_find_offsets(type_inner(&set->binary.lhs->type)); + void *ptr = (char *)struc.struc + set->binary.field->offset; + eval_deref_set(ptr, to, set->binary.field->type); + } break; + default: assert(0); break; } break; case EXPR_TUPLE: @@ -812,6 +820,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } if (o->type.kind == TYPE_ARR) v->ptr = id->val.arr; /* point directly to data */ + else if (o->type.kind == TYPE_STRUCT) + v->ptr = id->val.struc; else v->ptr = &id->val; } break; @@ -833,7 +843,14 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { return false; v->ptr = ptr; } break; - default: break; + case BINARY_DOT: { + Value struc; + if (!eval_expr(ev, o->binary.lhs, &struc)) + return false; + eval_struct_find_offsets(type_inner(&o->binary.lhs->type)); + v->ptr = (char *)struc.struc + o->binary.field->offset; + } break; + default: assert(0); break; } break; default: @@ -1163,7 +1180,6 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { while (inner_type->kind == TYPE_USER) inner_type = ident_typeval(type->user.name); if (inner_type->kind == TYPE_STRUCT) { - puts("Allocating space for struct"); id->val.struc = err_calloc(1, compiler_sizeof(inner_type)); } else if (inner_type->kind == TYPE_ARR) { id->val.arr = err_calloc(inner_type->arr.n, compiler_sizeof(inner_type->arr.of)); diff --git a/main.c b/main.c index 80e5371..ec7e164 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,5 @@ /* TODO: -. lvalue using dot with pointers length of slice/arr with .len verify size of struct, align of fields diff --git a/parse.c b/parse.c index 4e43eef..cb11412 100644 --- a/parse.c +++ b/parse.c @@ -957,7 +957,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { if (token_is_kw(t->token, KW_LPAREN)) tokr_err(t, "Direct function calling in an expression is not supported.\nYou can wrap the function in parentheses."); else - tokr_err(t, "Expected end of expression."); + tokr_err(t, "Expected end of function (did you forget a semicolon?)."); return false; } return true; diff --git a/test.toc b/test.toc index 4fdc819..3fc2dc2 100644 --- a/test.toc +++ b/test.toc @@ -4,28 +4,18 @@ puti @= fn(x: int) { }; Point @= struct { - x_coordinate, y_coordinate : int; - f : fn(); + x, y : int; }; -somefn @= fn() int { - p:Point; - x := p.({ - t @= int; - f @= fn() t { 7 as t }; - if f() as int > 3 { - "x_coordinate" - } else { - "y_coordinate" - } - }); - x +sum34 @= fn() int { + p: Point; + x := &p.x; + *x = 3; + p.y = 4; + p.x + p.y }; main @= fn() { - p: Point; - X @= somefn(); - puti(X); - puti(somefn()); - puti(p.x_coordinate); +X @= sum34(); +puti(sum34()); }; diff --git a/toc.c b/toc.c index 62ffc0b..243baaa 100644 --- a/toc.c +++ b/toc.c @@ -22,6 +22,14 @@ #include "tokenizer.c" #include "parse.c" #include "scope.c" + + +static Type *type_inner(Type *t) { + while (t->kind == TYPE_USER) + t = ident_typeval(t->user.name); + return t; +} + #include "eval.c" #include "types.c" static bool cgen_decls_file(CGenerator *g, ParsedFile *f); diff --git a/types.c b/types.c index 8769907..0726550 100644 --- a/types.c +++ b/types.c @@ -171,17 +171,18 @@ static bool expr_must_lval(Expression *e) { case EXPR_BINARY_OP: switch (e->binary.op) { case BINARY_AT_INDEX: return true; + case BINARY_DOT: return true; default: break; } - break; - case EXPR_TUPLE: { + err_print(e->where, "Cannot use operator %s as l-value", binary_op_to_str(e->binary.op)); + return false; + case EXPR_TUPLE: /* x, y is an lval, but 3, "hello" is not. */ arr_foreach(e->tuple, Expression, x) { if (!expr_must_lval(x)) return false; } return true; - } break; case EXPR_CAST: case EXPR_NEW: case EXPR_FN: @@ -1352,4 +1353,3 @@ static bool types_file(Typer *tr, ParsedFile *f) { static void typer_free(Typer *tr) { allocr_free_all(&tr->allocr); } - -- cgit v1.2.3