summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c112
1 files changed, 46 insertions, 66 deletions
diff --git a/eval.c b/eval.c
index e06dd9e..4150527 100644
--- a/eval.c
+++ b/eval.c
@@ -50,6 +50,7 @@ static size_t compiler_sizeof_builtin(BuiltinType b) {
}
static size_t compiler_alignof(Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
return compiler_sizeof_builtin(t->builtin);
@@ -70,19 +71,17 @@ static size_t compiler_alignof(Type *t) {
return sizeof(size_t);
case TYPE_TYPE:
return sizeof(Type *);
- case TYPE_USER:
- case TYPE_CALL:
- return compiler_alignof(type_user_underlying(t));
case TYPE_STRUCT: {
/* assume the align of a struct is (at most) the greatest align out of its children's */
size_t align = 1;
- arr_foreach(t->struc.fields, Field, f) {
+ arr_foreach(t->struc->fields, Field, f) {
size_t falign = compiler_alignof(f->type);
if (falign > align) align = falign;
}
return align;
}
case TYPE_UNKNOWN:
+ case TYPE_EXPR:
break;
}
assert(0);
@@ -90,12 +89,11 @@ static size_t compiler_alignof(Type *t) {
}
/* finds offsets and size */
-/* OPTIM: don't do this once per Type, but once per struct */
static void eval_struct_find_offsets(Type *t) {
assert(t->kind == TYPE_STRUCT);
- if (!(t->flags & TYPE_STRUCT_FOUND_OFFSETS)) {
+ if (!(t->struc->flags & STRUCT_DEF_FOUND_OFFSETS)) {
size_t bytes = 0;
- arr_foreach(t->struc.fields, Field, f) {
+ arr_foreach(t->struc->fields, Field, f) {
size_t falign = compiler_alignof(f->type);
/* align */
bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */
@@ -107,13 +105,14 @@ static void eval_struct_find_offsets(Type *t) {
/* final align */
size_t align = compiler_alignof(t);
bytes += ((align - bytes) % align + align) % align; /* = -bytes mod align */
- t->struc.size = bytes;
- t->flags |= TYPE_STRUCT_FOUND_OFFSETS;
+ t->struc->size = bytes;
+ t->struc->flags |= STRUCT_DEF_FOUND_OFFSETS;
}
}
/* size of a type at compile time */
static size_t compiler_sizeof(Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
return compiler_sizeof_builtin(t->builtin);
@@ -129,16 +128,15 @@ static size_t compiler_sizeof(Type *t) {
return sizeof(Slice);
case TYPE_TYPE:
return sizeof(Type *);
- case TYPE_USER:
- case TYPE_CALL:
- return compiler_sizeof(type_user_underlying(t));
case TYPE_STRUCT: {
eval_struct_find_offsets(t);
- return t->struc.size;
+ return t->struc->size;
} break;
case TYPE_VOID:
case TYPE_UNKNOWN:
return 0;
+ case TYPE_EXPR:
+ break;
}
assert(0);
return 0;
@@ -163,6 +161,7 @@ static bool builtin_truthiness(Value *v, BuiltinType b) {
}
static bool val_truthiness(Value *v, Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_VOID: return false;
case TYPE_UNKNOWN: assert(0); return false;
@@ -171,11 +170,10 @@ static bool val_truthiness(Value *v, Type *t) {
case TYPE_FN: return v->fn != NULL;
case TYPE_ARR: return t->arr.n > 0;
case TYPE_SLICE: return v->slice.n > 0;
- case TYPE_CALL:
- case TYPE_USER:
case TYPE_TYPE:
case TYPE_TUPLE:
case TYPE_STRUCT:
+ case TYPE_EXPR:
break;
}
assert(0);
@@ -238,6 +236,7 @@ static void u64_to_val(Value *v, BuiltinType v_type, U64 x) {
/* rerturns a pointer to the underlying data of v, e.g. an I64 * if t is the builtin BUILTIN_I64 */
static void *val_get_ptr(Value *v, Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_PTR:
case TYPE_BUILTIN:
@@ -248,19 +247,18 @@ static void *val_get_ptr(Value *v, Type *t) {
case TYPE_SLICE:
case TYPE_TYPE:
return v;
- case TYPE_USER:
- case TYPE_CALL:
- return val_get_ptr(v, type_user_underlying(t));
case TYPE_ARR:
return v->arr;
case TYPE_STRUCT:
return v->struc;
+ case TYPE_EXPR: break;
}
assert(0);
return NULL;
}
static void fprint_val_ptr(FILE *f, void *p, Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_VOID:
fprintf(f, "(void)");
@@ -323,14 +321,10 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
case TYPE_TYPE:
fprint_type(f, *(Type **)p);
break;
- case TYPE_USER:
- case TYPE_CALL:
- fprint_val_ptr(f, p, type_user_underlying(t));
- break;
case TYPE_STRUCT:
fprintf(f, "["); /* TODO: change? when struct initializers are added */
- arr_foreach(t->struc.fields, Field, fi) {
- if (fi != t->struc.fields)
+ arr_foreach(t->struc->fields, Field, fi) {
+ if (fi != t->struc->fields)
fprintf(f, ", ");
fprint_ident(f, fi->name);
fprintf(f, ": ");
@@ -338,7 +332,9 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
}
fprintf(f, "]");
break;
+ case TYPE_EXPR: break;
}
+ assert(0);
}
static void fprint_val(FILE *f, Value v, Type *t) {
@@ -354,6 +350,7 @@ static void fprint_val(FILE *f, Value v, Type *t) {
}
static void *val_ptr_to_free(Value *v, Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
case TYPE_FN:
@@ -361,17 +358,17 @@ static void *val_ptr_to_free(Value *v, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
- case TYPE_TYPE:
return NULL;
+ case TYPE_TYPE:
+ return v->type->was_expr;
case TYPE_ARR:
return v->arr;
case TYPE_TUPLE:
return v->tuple;
case TYPE_STRUCT:
return v->struc;
- case TYPE_USER:
- case TYPE_CALL:
- return val_ptr_to_free(v, type_user_underlying(t));
+ case TYPE_EXPR:
+ break;
}
assert(0); return NULL;
}
@@ -454,24 +451,21 @@ static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinT
}
static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
+ assert(from->flags & TYPE_IS_RESOLVED);
+ assert(to->flags & TYPE_IS_RESOLVED);
+
if (to->kind == TYPE_BUILTIN && to->builtin == BUILTIN_BOOL) {
vout->boolv = val_truthiness(vin, from);
return;
}
- if (from->kind == TYPE_USER || to->kind == TYPE_USER
- || from->kind == TYPE_CALL || to->kind == TYPE_CALL) {
- *vout = *vin;
- return;
- }
switch (from->kind) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
- case TYPE_USER:
- case TYPE_CALL:
case TYPE_TYPE:
case TYPE_STRUCT:
+ case TYPE_EXPR:
assert(0); break;
case TYPE_BUILTIN:
switch (to->kind) {
@@ -491,8 +485,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
default: assert(0); break;
}
break;
- case TYPE_USER:
- case TYPE_CALL:
+ case TYPE_EXPR:
case TYPE_STRUCT:
case TYPE_SLICE:
case TYPE_VOID:
@@ -514,8 +507,6 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_FN:
vout->fn = vin->fn;
break;
- case TYPE_USER:
- case TYPE_CALL:
case TYPE_SLICE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
@@ -524,6 +515,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_BUILTIN:
case TYPE_TYPE:
case TYPE_STRUCT:
+ case TYPE_EXPR:
assert(0); break;
}
break;
@@ -549,12 +541,11 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_FN:
vout->fn = vin->ptr;
break;
- case TYPE_USER:
- case TYPE_CALL:
case TYPE_SLICE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
+ case TYPE_EXPR:
case TYPE_TYPE:
case TYPE_STRUCT:
assert(0);
@@ -570,8 +561,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_ARR:
vout->arr = vin->arr;
break;
- case TYPE_USER:
- case TYPE_CALL:
+ case TYPE_EXPR:
case TYPE_SLICE:
case TYPE_FN:
case TYPE_UNKNOWN:
@@ -594,13 +584,12 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_SLICE:
vout->slice = vin->slice;
break;
- case TYPE_USER:
- case TYPE_CALL:
case TYPE_FN:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
case TYPE_BUILTIN:
+ case TYPE_EXPR:
case TYPE_TYPE:
case TYPE_STRUCT:
assert(0); break;
@@ -611,6 +600,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
/* type is the underlying type, not the pointer type. */
static void eval_deref(Value *v, void *ptr, Type *type) {
+ assert(type->flags & TYPE_IS_RESOLVED);
switch (type->kind) {
case TYPE_PTR: v->ptr = *(void **)ptr; break;
case TYPE_ARR: v->arr = ptr; break; /* when we have a pointer to an array, it points directly to the data in that array. */
@@ -639,18 +629,16 @@ static void eval_deref(Value *v, void *ptr, Type *type) {
case TYPE_TYPE:
v->type = *(Type **)ptr;
break;
- case TYPE_USER:
- case TYPE_CALL:
- eval_deref(v, ptr, type_user_underlying(type));
- break;
case TYPE_VOID:
case TYPE_UNKNOWN:
+ case TYPE_EXPR:
assert(0);
break;
}
}
/* inverse of eval_deref */
static void eval_deref_set(void *set, Value *to, Type *type) {
+ assert(type->flags & TYPE_IS_RESOLVED);
switch (type->kind) {
case TYPE_PTR: *(void **)set = to->ptr; break;
case TYPE_ARR: memcpy(set, to->arr, compiler_sizeof(type)); break; /* TODO: test this */
@@ -679,12 +667,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
case TYPE_TYPE:
*(Type **)set = to->type;
break;
- case TYPE_USER:
- case TYPE_CALL:
- eval_deref_set(set, to, type_user_underlying(type));
- break;
case TYPE_VOID:
case TYPE_UNKNOWN:
+ case TYPE_EXPR:
assert(0);
break;
}
@@ -738,10 +723,10 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ
}
static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) {
- Type *struct_type = type_inner(&dot_expr->binary.lhs->type);
+ Type *struct_type = &dot_expr->binary.lhs->type;
bool is_ptr = struct_type->kind == TYPE_PTR;
if (is_ptr) {
- struct_type = type_inner(struct_type->ptr);
+ struct_type = struct_type->ptr;
}
eval_struct_find_offsets(struct_type);
@@ -991,7 +976,6 @@ 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));
@@ -1194,7 +1178,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Value from, to;
Value stepval;
stepval.i64 = 1;
- Type i64t;
+ Type i64t = {0};
i64t.flags = TYPE_IS_RESOLVED;
i64t.kind = TYPE_BUILTIN;
i64t.builtin = BUILTIN_I64;
@@ -1228,7 +1212,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Value lhs = x;
Value rhs = to;
assert(ea->type.kind == TYPE_BUILTIN);
- Type boolt;
+ Type boolt = {0};
boolt.flags = TYPE_IS_RESOLVED;
boolt.kind = TYPE_BUILTIN;
boolt.builtin = BUILTIN_BOOL;
@@ -1345,15 +1329,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
}
int index = ident_index_in_decl(e->ident, d);
assert(index != -1);
+ *v = *decl_val_at_index(d, index);
if (e->type.kind == TYPE_TYPE) {
- /* set v to a user type, not the underlying type */
- v->type = evalr_malloc(ev, sizeof *v->type); /* TODO: fix this (free eventually) */
- v->type->flags = TYPE_IS_RESOLVED;
- v->type->kind = TYPE_USER;
- v->type->user.decl = d;
- v->type->user.index = index;
- } else {
- *v = *decl_val_at_index(d, index);
+ /* make sure was_expr is set */
+ /* NOTE: this will be freed (see val_ptr_to_free) */
+ v->type->was_expr = err_malloc(sizeof *v->type->was_expr);
}
} else {
char *s = ident_to_str(e->ident);