summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-14 13:55:12 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-14 13:55:12 -0500
commite631bb0147147caf36a2b4ef63c7561f8221da02 (patch)
treee2f20e67ac547c7c7f57bdfe44d395595fff1159
parente9bc97fa6f5251d6ebb476e3167b887e098e83ff (diff)
cleaning up some stuff
-rwxr-xr-xbuild.sh13
-rw-r--r--cgen.c88
-rw-r--r--eval.c109
-rw-r--r--main.c12
-rw-r--r--parse.c5
-rw-r--r--scope.c2
-rw-r--r--test.toc25
-rw-r--r--tokenizer.c5
-rw-r--r--typedefs_cgen.c2
-rw-r--r--types.c89
10 files changed, 163 insertions, 187 deletions
diff --git a/build.sh b/build.sh
index 3e3760c..abce67c 100755
--- a/build.sh
+++ b/build.sh
@@ -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"
diff --git a/cgen.c b/cgen.c
index 971d2c3..838d6ef 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
diff --git a/eval.c b/eval.c
index 6aa5250..2c750a3 100644
--- a/eval.c
+++ b/eval.c
@@ -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++;
diff --git a/main.c b/main.c
index 1e84054..f510b34 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/parse.c b/parse.c
index ddad492..9112a0a 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/scope.c b/scope.c
index b0ebbeb..ab123fe 100644
--- a/scope.c
+++ b/scope.c
@@ -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) {
diff --git a/test.toc b/test.toc
index 8181d0d..b2499df 100644
--- a/test.toc
+++ b/test.toc
@@ -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++;
diff --git a/types.c b/types.c
index ec90736..2fd0755 100644
--- a/types.c
+++ b/types.c
@@ -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;
}
}