diff options
-rw-r--r-- | eval.c | 66 | ||||
-rw-r--r-- | scope.c | 5 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | types.c | 2 |
4 files changed, 69 insertions, 6 deletions
@@ -396,6 +396,7 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { case UNARY_DEREF: { Value ptr; if (!eval_expr(ev, set->unary.of, &ptr)) return false; + printf("%p\n",ptr.ptr); eval_deref_set(ptr.ptr, to, &set->type); } break; default: assert(0); break; @@ -519,11 +520,65 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { switch (e->kind) { case EXPR_UNARY_OP: { Value of; - if (!eval_expr(ev, e->unary.of, &of)) return false; + if (e->unary.op != UNARY_ADDRESS) { + if (!eval_expr(ev, e->unary.of, &of)) return false; + } switch (e->unary.op) { - case UNARY_ADDRESS: - /* TODO */ - break; + case UNARY_ADDRESS: { + Expression *o = e->unary.of; + switch (o->kind) { + case EXPR_IDENT: { + IdentDecl *id = ident_decl(o->ident); + if (!(id->flags & IDECL_FLAG_HAS_VAL)) { + err_print(e->where, "Cannot take address of run time variable at compile time."); + return false; + } + v->ptr = &id->val; + } break; + case EXPR_UNARY_OP: + switch (o->unary.op) { + case UNARY_DEREF: { + Value ptr; + if (!eval_expr(ev, o, &ptr)) return false; + v->ptr = ptr.ptr; + } break; + default: assert(0); break; + } + break; + case EXPR_BINARY_OP: + switch (o->binary.op) { + case BINARY_AT_INDEX: { + Value arr; + if (!eval_expr(ev, o->binary.lhs, &arr)) return false; + Value index; + if (!eval_expr(ev, o->binary.rhs, &index)) return false; + U64 i; + U64 arr_sz = o->binary.lhs->type.arr.n; + assert(o->binary.rhs->type.kind == TYPE_BUILTIN); + if (o->binary.rhs->type.builtin == BUILTIN_U64) { + i = index.u64; + } else { + I64 signed_index = val_to_i64(&index, o->binary.rhs->type.builtin); + if (signed_index < 0) { + err_print(o->where, "Array out of bounds (%ld, array size = %lu)\n", (long)signed_index, (unsigned long)arr_sz); + return false; + } + i = (U64)signed_index; + } + if (i >= arr_sz) { + err_print(o->where, "Array out of bounds (%lu, array size = %lu)\n", (unsigned long)i, (unsigned long)arr_sz); + return false; + } + v->ptr = (char *)arr.arr + compiler_sizeof(&o->binary.lhs->type) * i; + } break; + default: break; + } + break; + default: + assert(0); + break; + } + } break; case UNARY_DEREF: eval_deref(v, of.ptr, &e->type); break; @@ -727,6 +782,9 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { if (d->flags & DECL_FLAG_HAS_EXPR) { if (!eval_expr(ev, &d->expr, &id->val)) return false; + } else if (d->type.kind == TYPE_ARR) { + /* stack array allocation */ + id->val.arr = err_calloc(d->type.arr.n, compiler_sizeof(d->type.arr.of)); } else { id->val = (Value){0}; } @@ -23,6 +23,11 @@ static void remove_ident_decls(Block *b, Declaration *d) { IdentDecl **decls = &id_info->decls; IdentDecl *last_decl = arr_last(*decls); if (last_decl && last_decl->scope == b) { + if ((last_decl->flags & IDECL_FLAG_HAS_VAL) + && last_decl->decl->type.kind == TYPE_ARR) { + /* free array on stack */ + free(last_decl->val.arr); + } arr_remove_last(decls); /* remove that declaration */ } } @@ -3,5 +3,5 @@ main @= fn() { // N, M @= 8 * if foo { 8 } else { 3} - 3, 894; // foo @= new[3]int; // x : [foo[0]]int; - y : [{x : [3]int; x[0] = 7; x[0] }]f32; + y : [{x : [3]int; p : &int = &x[2]; *p = 734; x[2] }]f32; };
\ No newline at end of file @@ -82,7 +82,7 @@ static bool type_must_eq(Location where, Type *expected, Type *got) { /* sometimes prints an error and returns false if the given expression is not an l-value */ static bool expr_must_lval(Expression *e) { - /* NOTE: make sure you update eval_expr's UNARY_ADDRESS when you change this */ + /* NOTE: make sure you update eval when you change this */ switch (e->kind) { case EXPR_IDENT: { IdentDecl *id_decl = ident_decl(e->ident); |