diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-14 13:55:12 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-14 13:55:12 -0500 |
commit | e631bb0147147caf36a2b4ef63c7561f8221da02 (patch) | |
tree | e2f20e67ac547c7c7f57bdfe44d395595fff1159 | |
parent | e9bc97fa6f5251d6ebb476e3167b887e098e83ff (diff) |
cleaning up some stuff
-rwxr-xr-x | build.sh | 13 | ||||
-rw-r--r-- | cgen.c | 88 | ||||
-rw-r--r-- | eval.c | 109 | ||||
-rw-r--r-- | main.c | 12 | ||||
-rw-r--r-- | parse.c | 5 | ||||
-rw-r--r-- | scope.c | 2 | ||||
-rw-r--r-- | test.toc | 25 | ||||
-rw-r--r-- | tokenizer.c | 5 | ||||
-rw-r--r-- | typedefs_cgen.c | 2 | ||||
-rw-r--r-- | types.c | 89 |
10 files changed, 163 insertions, 187 deletions
@@ -6,20 +6,13 @@ if [ "$CC" = "" ]; then CC=gcc fi fi - -# Possible extra build flags -# these are for compiling the compiler, and NOT for compiling the program itself. -# -DNONZERO_NULL_PTRS -# - must be set if the zero value of a pointer (as might be set by calloc/memset) -# is not the NULL pointer. - -# ADDITIONAL_FLAGS='-Wno-unused-function' +ADDITIONAL_FLAGS="$CFLAGS -Wno-unused-function" if [ "$CC" = "clang" ]; then - WARNINGS='-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wimplicit-fallthrough -Wno-unused-parameter' + WARNINGS='-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wimplicit-fallthrough' else - WARNINGS='-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-pointer-to-int-cast -Wno-unused-parameter' + WARNINGS='-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-pointer-to-int-cast' fi DEBUG_FLAGS="-O0 -g3 $WARNINGS -std=c11 -DTOC_DEBUG" @@ -84,7 +84,7 @@ static bool cgen_defs_block(CGenerator *g, Block *b); break; \ case EXPR_EACH: { \ EachExpr *ea = &e->each; \ - if (!each_enter(e, 0)) return false; \ + if (!each_enter(e)) return false; \ if (ea->flags & EACH_IS_RANGE) { \ if (!f(g, ea->range.from)) \ return false; \ @@ -203,8 +203,8 @@ static bool cgen_uses_ptr(Type *t) { switch (t->kind) { case TYPE_TUPLE: case TYPE_STRUCT: + case TYPE_ARR: return true; - case TYPE_ARR: /* TODO: test me */ case TYPE_BUILTIN: case TYPE_PTR: case TYPE_FN: @@ -587,18 +587,26 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, case EXPR_CALL: { /* e.g. a, b = fn_which_returns_tuple(); */ if (!cgen_expr(g, to->call.fn)) return false; + if (to->call.c.instance) + cgen_write(g, "%"PRId64, to->call.c.instance); cgen_write(g, "("); - bool any_args = arr_len(to->call.arg_exprs) != 0; + bool any_args = false; + bool *constant = to->call.fn->type.fn.constant; + int i = 0; arr_foreach(to->call.arg_exprs, Expression, arg) { - if (arg != to->call.arg_exprs) - cgen_write(g, ", "); - if (!cgen_expr(g, arg)) - return false; + if (!constant || !constant[i]) { + if (any_args) + cgen_write(g, ", "); + any_args = true; + if (!cgen_expr(g, arg)) + return false; + } + i++; } /* out params */ size_t len = exprs ? arr_len(exprs) : arr_len(idents); - for (unsigned long i = 0; i < (unsigned long)len; i++) { + for (i = 0; i < (int)len; i++) { if (any_args || i > 0) cgen_write(g, ", "); if (exprs) { @@ -609,7 +617,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, cgen_write(g, "&"); cgen_ident(g, idents[i]); } else { - cgen_write(g, "&(%s%lu_)", prefix, i); + cgen_write(g, "&(%s%d_)", prefix, i); } } cgen_writeln(g, "); "); @@ -745,7 +753,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { } ea->c.id = id; - if (!each_enter(e, 0)) return false; + if (!each_enter(e)) return false; cgen_write(g, "{"); if (is_range) { if (ea->range.to) { @@ -946,14 +954,20 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { if (!cgen_type_post(g, &e->type, e->where)) return false; cgen_write(g, ";"); cgen_nl(g); if (!cgen_expr(g, e->call.fn)) return false; + if (e->call.c.instance) { + cgen_write(g, "%"PRId64, e->call.c.instance); + } cgen_write(g, "("); bool any_args = false; + i = 0; arr_foreach(e->call.arg_exprs, Expression, arg) { - any_args = true; - if (arg != e->call.arg_exprs) - cgen_write(g, ", "); - if (!cgen_expr(g, arg)) - return false; + if (!constant || !constant[i]) { + if (any_args) cgen_write(g, ", "); + any_args = true; + if (!cgen_expr(g, arg)) + return false; + } + i++; } if (any_args) { cgen_write(g, ", "); @@ -1283,35 +1297,26 @@ static bool cgen_expr(CGenerator *g, Expression *e) { case EXPR_CALL: if (cgen_uses_ptr(&e->type)) { cgen_ident_id(g, e->call.c.id); - } else if (e->call.c.instance) { + } else { + FnType *fn_type = &e->call.fn->type.fn; cgen_write(g, "("); if (!cgen_expr(g, e->call.fn)) return false; - cgen_write(g, "%"PRId64"(", e->call.c.instance); - Expression *args = e->call.arg_exprs; - FnType *fn_type = &e->call.fn->type.fn; + if (e->call.c.instance) { + cgen_write(g, "%"PRId64, e->call.c.instance); + } + cgen_write(g, "("); bool first_arg = true; - for (size_t i = 0; i < arr_len(fn_type->types)-1; i++) { - if (!fn_type->constant[i]) { + size_t i = 0; + arr_foreach(e->call.arg_exprs, Expression, arg) { + if (!fn_type->constant || !fn_type->constant[i]) { if (!first_arg) cgen_write(g, ", "); first_arg = false; - if (!cgen_expr(g, &args[i])) + if (!cgen_expr(g, arg)) return false; } - } - cgen_write(g, ")"); - cgen_write(g, ")"); - } else { - cgen_write(g, "("); - if (!cgen_expr(g, e->call.fn)) - return false; - cgen_write(g, "("); - arr_foreach(e->call.arg_exprs, Expression, arg) { - if (arg != e->call.arg_exprs) - cgen_write(g, ", "); - if (!cgen_expr(g, arg)) - return false; + i++; } cgen_write(g, "))"); } @@ -1507,6 +1512,8 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where, I64 instance, Valu if (!cgen_ret(g, &ret_expr)) return false; + if (ret_expr.kind == EXPR_TUPLE) + arr_clear(&ret_expr.tuple); } else if (f->body.ret_expr) { if (!cgen_ret(g, f->body.ret_expr)) return false; } @@ -1579,7 +1586,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { cgen_write(g, "{"); for (size_t i = 0; i < t->arr.n; i++) { if (i) cgen_write(g, ", "); - if (!cgen_val_ptr(g, *(char **)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) + if (!cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) return false; } cgen_write(g, "}"); @@ -1588,8 +1595,13 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { cgen_write(g, "{d%p_, %lu}", v, ((Slice *)v)->n); break; case TYPE_STRUCT: - err_print(where, "TODO"); - /* TODO */ + cgen_write(g, "{"); + arr_foreach(t->struc.fields, Field, f) { + if (f != t->struc.fields) + cgen_write(g, ", "); + cgen_val_ptr(g, (char *)v + f->offset, f->type, where); + } + cgen_write(g, "}"); break; case TYPE_FN: cgen_fn_name(g, *(FnExpr **)v); @@ -29,6 +29,7 @@ static inline void *evalr_calloc(Evaluator *ev, size_t n, size_t bytes) { return allocr_calloc(ev->allocr, n, bytes); } + static size_t compiler_sizeof_builtin(BuiltinType b) { switch (b) { case BUILTIN_I8: return sizeof(I8); @@ -348,10 +349,9 @@ static void fprint_val(FILE *f, Value v, Type *t) { } /* - IMPORTANT: Only pass an evaluator if you want it to use its allocator. - Otherwise, pass NULL. +allocr can be NULL */ -static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) { +static void val_copy(Allocator *allocr, Value *dest, Value *src, Type *t) { switch (t->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -364,30 +364,30 @@ static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) { break; case TYPE_ARR: { size_t bytes = t->arr.n * compiler_sizeof(t->arr.of); - if (ev) - dest->arr = evalr_malloc(ev, bytes); + if (allocr) + dest->arr = allocr_malloc(allocr, bytes); else dest->arr = err_malloc(bytes); memcpy(dest->arr, src->arr, bytes); } break; case TYPE_TUPLE: { size_t bytes = arr_len(t->tuple) * sizeof(*dest->tuple); - if (ev) - dest->tuple = evalr_malloc(ev, bytes); + if (allocr) + dest->tuple = allocr_malloc(allocr, bytes); else dest->tuple = err_malloc(bytes); memcpy(dest->tuple, src->tuple, bytes); } break; case TYPE_STRUCT: { size_t bytes = compiler_sizeof(t); - if (ev) - dest->struc = evalr_malloc(ev, bytes); + if (allocr) + dest->struc = allocr_malloc(allocr, bytes); else dest->struc = err_malloc(bytes); memcpy(dest->struc, src->struc, bytes); } break; case TYPE_USER: - val_copy(ev, dest, src, type_user_underlying(t)); + val_copy(allocr, dest, src, type_user_underlying(t)); break; } } @@ -727,7 +727,7 @@ static void eval_deref_set(void *set, Value *to, Type *type) { } } -static bool eval_val_ptr_at_index(Evaluator *ev, Location where, Value *arr, U64 i, Type *arr_type, Type *idx_type, void **ptr, Type **type) { +static bool eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_type, void **ptr, Type **type) { switch (arr_type->kind) { case TYPE_ARR: { U64 arr_sz = (U64)arr_type->arr.n; @@ -771,7 +771,7 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ } i = (U64)signed_index; } - return eval_val_ptr_at_index(ev, e->where, &arr, i, ltype, rtype, ptr, type); + return eval_val_ptr_at_index(e->where, &arr, i, ltype, ptr, type); } static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) { @@ -1026,6 +1026,22 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value } +static Value val_zero(Type *t) { + Value val = {0}; + t = type_inner(t); + switch (t->kind) { + case TYPE_STRUCT: + val.struc = err_calloc(1, compiler_sizeof(t)); + break; + case TYPE_ARR: + val.arr = err_calloc(t->arr.n, compiler_sizeof(t->arr.of)); + break; + default: + break; + } + return val; +} + static bool val_is_nonnegative(Value *v, Type *t) { switch (t->builtin) { case BUILTIN_BOOL: assert(0); return false; @@ -1226,7 +1242,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value x = from; Value *index_val; Value *value_val; - if (!each_enter(e, 0)) return false; + if (!each_enter(e)) return false; if (ea->index) { IdentDecl *idecl = ident_decl(ea->index); idecl->flags |= IDECL_HAS_VAL; @@ -1272,7 +1288,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_expr(ev, ea->of, &of)) return false; Value *index_val, *value_val; Value i, val; - if (!each_enter(e, 0)) return false; + if (!each_enter(e)) return false; if (ea->index) { IdentDecl *idecl = ident_decl(ea->index); idecl->flags |= IDECL_HAS_VAL; @@ -1310,14 +1326,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { break; default: assert(0); return false; } - Type i64t; - i64t.flags = TYPE_IS_RESOLVED; - i64t.kind = TYPE_BUILTIN; - i64t.builtin = BUILTIN_I64; + index_val->i64 = 0; while (index_val->i64 < len) { void *ptr; - if (!eval_val_ptr_at_index(ev, e->where, &of, (U64)index_val->i64, of_type, &i64t, &ptr, NULL)) + if (!eval_val_ptr_at_index(e->where, &of, (U64)index_val->i64, of_type, &ptr, NULL)) return false; if (uses_ptr) value_val->ptr = ptr; @@ -1451,7 +1464,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { fn_enter(fn, 0); long arg = 0; arr_foreach(params, Declaration, p) { - long idx = 0; + int idx = 0; arr_foreach(p->idents, Identifier, i) { Type *type = p->type.kind == TYPE_TUPLE ? &p->type.tuple[idx++] : &p->type; IdentDecl *id = ident_decl(*i); @@ -1460,13 +1473,54 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { arg++; } } + arr_foreach(fn->ret_decls, Declaration, d) { + int idx = 0; + arr_foreach(d->idents, Identifier, i) { + Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx++] : &d->type; + IdentDecl *id = ident_decl(*i); + if (d->flags & DECL_HAS_EXPR) { + assert(d->expr.kind == EXPR_VAL); + val_copy(NULL, &id->val, &d->expr.val, type); + id->flags |= IDECL_HAS_VAL; + } else { + id->flags |= IDECL_HAS_VAL; + id->val = val_zero(type); + } + } + } arr_clear(&args); if (!eval_block(ev, &fn->body, &e->type, v)) { fn_exit(fn); return false; } + if (fn->ret_decls) { + Value *tuple = NULL; + arr_foreach(fn->ret_decls, Declaration, d) { + int i = 0; + arr_foreach(d->idents, Identifier, ident) { + Value this_one; + Expression expr; + expr.flags = EXPR_FOUND_TYPE; + expr.kind = EXPR_IDENT; + expr.ident = *ident; + if (!eval_expr(ev, &expr, &this_one)) + return false; + Value *element = arr_add(&tuple); + Type *type = decl_type_at_index(d, i); + val_copy(NULL, element, &this_one, type); + i++; + } + } + if (arr_len(tuple) == 1) { + *v = tuple[0]; + arr_clear(&tuple); + } else { + v->tuple = tuple; + } + } if (ev->returning) { - *v = ev->ret_val; + if (fn->ret_type.kind != TYPE_VOID && !fn->ret_decls) + *v = ev->ret_val; ev->returning = false; } fn_exit(fn); @@ -1504,9 +1558,9 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } void *ptr1, *ptr2; if (from < to) { - if (!eval_val_ptr_at_index(ev, e->where, &ofv, from, of_type, &s->from->type, &ptr1, NULL)) + if (!eval_val_ptr_at_index(e->where, &ofv, from, of_type, &ptr1, NULL)) return false; - if (!eval_val_ptr_at_index(ev, e->where, &ofv, to, of_type, &s->to->type, &ptr2, NULL)) + if (!eval_val_ptr_at_index(e->where, &ofv, to, of_type, &ptr2, NULL)) return false; v->slice.data = ptr1; v->slice.n = (I64)(to - from); @@ -1549,18 +1603,11 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { arr_foreach(d->idents, Identifier, i) { IdentDecl *id = ident_decl(*i); Type *type = decl_type_at_index(d, index); - Type *inner = type_inner(type); if (!is_const) { if (has_expr) { val_copy(NULL, &id->val, &val, type); } else { - if (inner->kind == TYPE_STRUCT) { - id->val.struc = err_calloc(1, compiler_sizeof(inner)); - } else if (inner->kind == TYPE_ARR) { - id->val.arr = err_calloc(inner->arr.n, compiler_sizeof(inner->arr.of)); - } else { - id->val = val; /* = (Value)({0}) */ - } + id->val = val_zero(type); } } index++; @@ -1,14 +1,12 @@ /* TODO: -running release build under valgrind produces an error that shouldn't be there!!! -memory leaks! -deal with unused functions -compile time arguments + out parameters (in C) -double check that val_get_ptr is being used everywhere it should be -compile-time arguments for out parameter functions -compile-time arguments for functions returning tuples +ah need to be consistent about whether eval_expr returns a value which should be copied or not!!! +check for leaks +make sure return declarations with initializers work (also, eval initializers) deal with x, y @= fn(x: int, y @ int){} don't allow pointers to functions with compile-time arguments +type parameters (e.g. fn(foo @ type) {x: foo;}) + struct parameters don't allow while {3; 5} (once break is added) any odd number of "s for a string @@ -232,6 +232,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { ? t->user.decl->idents[t->user.index] : t->user.ident); size_t ret = str_copy(buffer, bufsize, ident_str); + free(ident_str); return ret; } } @@ -2177,8 +2178,8 @@ static void fprint_parsed_file(FILE *out, ParsedFile *f) { } } -static long decl_ident_index(Declaration *d, Identifier i) { - long idx = 0; +static int decl_ident_index(Declaration *d, Identifier i) { + int idx = 0; arr_foreach(d->idents, Identifier, j) { if (i == *j) return idx; @@ -80,7 +80,7 @@ static void fn_exit(FnExpr *f) { remove_ident_decls(&f->body, decl); } -static bool each_enter(Expression *e, U32 flags) { +static bool each_enter(Expression *e) { assert(e->kind == EXPR_EACH); EachExpr *ea = &e->each; if (ea->index && ea->index == ea->value) { @@ -3,26 +3,21 @@ puti @= fn(x: int) { "); }; -☃ @= struct { + +Foo @= struct { x, y: int; z: float; }; -something @= fn() int { - 5 -}; -bar @= fn(a := something()) f: ☃, g: int { - f.x = a; - f.y = 123; - f.z += 43.2; - g = 17; +mkfoo @= fn() f: Foo { + f.x = 12; + f.y = -983; + f.z = 21.34-1.2; }; + main @= fn() { -f,g := bar(); -puti(g); -puti(f.x); -puti(f.y); -h,i := bar(); -puti(h.x); + f @= mkfoo(); + puti(f.x); + puti(f.y); }; diff --git a/tokenizer.c b/tokenizer.c index 539f2cd..06ffdcc 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -310,7 +310,6 @@ static bool tokenize_string(Tokenizer *t, char *str) { } } } - while (1) { if (*t->s == '.') { if (t->s[1] == '.') { @@ -382,8 +381,8 @@ static bool tokenize_string(Tokenizer *t, char *str) { } switch (n.kind) { case NUM_LITERAL_INT: - if (n.intval > UINTEGER_MAX / (UInteger)base || - n.intval * (UInteger)base > UINT_MAX - (UInteger)digit) { + if ((UInteger)n.intval > (UInteger)UINTEGER_MAX / (UInteger)base || + (UInteger)n.intval * (UInteger)base > (UInteger)UINTEGER_MAX - (UInteger)digit) { /* too big! */ tokenization_err(t, "Number too big to fit in a numeric literal."); goto err; diff --git a/typedefs_cgen.c b/typedefs_cgen.c index 879eb2f..a6453de 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -31,7 +31,7 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) { Value *val = decl_val_at_index(d, idx); if (type->kind == TYPE_TYPE) { if (d->c.ids == NULL) - d->c.ids = calloc(arr_len(d->idents), sizeof *d->c.ids); + d->c.ids = allocr_calloc(g->allocr, arr_len(d->idents), sizeof *d->c.ids); /* generate typedef */ IdentID id = 0; if (g->block != NULL) id = d->c.ids[idx] = g->ident_counter++; @@ -94,67 +94,6 @@ static bool type_must_eq(Location where, Type *expected, Type *got) { return true; } - -/* - this expression, which is an array (or slice), must be mutable (otherwise print an error, - return false)! -*/ -static bool expr_arr_must_mut(Expression *e) { - switch (e->kind) { - case EXPR_IDENT: { - IdentDecl *idecl = ident_decl(e->ident); - if (idecl->kind == IDECL_DECL) { - Declaration *d = idecl->decl; - if (d->flags & DECL_IS_CONST) { - err_print(e->where, "Cannot modify a constant array."); - return false; - } - } - return true; - } - case EXPR_CAST: - case EXPR_CALL: - case EXPR_NEW: - case EXPR_UNARY_OP: - case EXPR_C: - case EXPR_VAL: - return true; - case EXPR_SLICE: - return expr_arr_must_mut(e->slice.of); - case EXPR_WHILE: - assert(e->while_.body.ret_expr); - return expr_arr_must_mut(e->while_.body.ret_expr); - case EXPR_EACH: - return expr_arr_must_mut(e->each.body.ret_expr); - case EXPR_IF: - for (IfExpr *i = &e->if_; i; i->next_elif ? i = &i->next_elif->if_ : (i = NULL)) { - assert(i->body.ret_expr); - if (!expr_arr_must_mut(i->body.ret_expr)) - return false; - } - return true; - case EXPR_BLOCK: - assert(e->block.ret_expr); - return expr_arr_must_mut(e->block.ret_expr); - case EXPR_LITERAL_STR: - err_print(e->where, "String constants are immutable."); - return false; - case EXPR_LITERAL_BOOL: - case EXPR_FN: - case EXPR_TUPLE: - case EXPR_LITERAL_FLOAT: - case EXPR_LITERAL_CHAR: - case EXPR_LITERAL_INT: - case EXPR_BINARY_OP: - case EXPR_TYPE: - case EXPR_DALIGNOF: - case EXPR_DSIZEOF: - break; - } - assert(0); - return false; -} - /* 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 when you change this */ @@ -190,7 +129,10 @@ static bool expr_must_lval(Expression *e) { return false; case EXPR_BINARY_OP: switch (e->binary.op) { - case BINARY_AT_INDEX: return true; + case BINARY_AT_INDEX: + if (!expr_must_lval(e->binary.lhs)) + return false; + return true; case BINARY_DOT: return true; default: break; } @@ -327,20 +269,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } if (d->flags & DECL_FOUND_TYPE) { - if (d->type.kind == TYPE_TUPLE) { - /* get correct item in tuple */ - long index = 0; - arr_foreach(d->idents, Identifier, decl_i) { - if (*decl_i == i) { - break; - } - index++; - assert(index < (long)arr_len(d->idents)); /* identifier got its declaration set to here, but it's not here */ - } - *t = d->type.tuple[index]; - } else { - *t = d->type; - } + *t = *decl_type_at_index(d, decl_ident_index(d, i)); return true; } else { if ((d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { @@ -705,7 +634,7 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_EACH: { EachExpr *ea = &e->each; *(Expression **)arr_add(&tr->in_expr_decls) = e; - if (!each_enter(e, SCOPE_CHECK_REDECL)) return false; + if (!each_enter(e)) return false; if (ea->flags & EACH_IS_RANGE) { /* TODO: allow user-defined numerical types */ if (!types_expr(tr, ea->range.from)) return false; @@ -1560,14 +1489,16 @@ static bool types_decl(Typer *tr, Declaration *d) { goto ret; } d->type = d->expr.type; - d->type.flags &= (uint16_t)~(uint16_t)TYPE_IS_FLEXIBLE; /* x := 5; => x is not flexible */ + d->type.flags &= (U16)~(U16)TYPE_IS_FLEXIBLE; /* x := 5; => x is not flexible */ } if ((d->flags & DECL_IS_CONST) || (tr->block == NULL && tr->fn == NULL)) { if (!(d->flags & DECL_FOUND_VAL)) { - if (!eval_expr(tr->evalr, &d->expr, &d->val)) { + Value val; + if (!eval_expr(tr->evalr, &d->expr, &val)) { success = false; goto ret; } + val_copy(tr->allocr, &d->val, &val, &d->type); d->flags |= DECL_FOUND_VAL; } } |