summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-31 17:10:36 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-31 17:10:36 -0400
commit9e55cdb1ea5cd8318a1a0b7a9f64f09e8d8ad692 (patch)
treedd30665fb9ad6e40f1bead09bda20b53e5a8e184
parent4322b5897449db33bb8c22bae13726c285708009 (diff)
a.b as an lvalue
-rw-r--r--eval.c22
-rw-r--r--main.c1
-rw-r--r--parse.c2
-rw-r--r--test.toc28
-rw-r--r--toc.c8
-rw-r--r--types.c8
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);
}
-