summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-09-28 23:20:18 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-09-28 23:20:18 -0400
commit1318715bdf9a7c7da86913094d9ad7ad52779333 (patch)
tree6d3a2e75c64a00aa0906aa152b67ee11ec59dd8a
parent119046ec01f16c388fdc38fcceca372f43c034c8 (diff)
eval - more casting and other improvements
-rw-r--r--eval.c153
-rw-r--r--main.c1
-rw-r--r--test.toc26
-rw-r--r--types.c6
4 files changed, 154 insertions, 32 deletions
diff --git a/eval.c b/eval.c
index c6b1b56..8274da8 100644
--- a/eval.c
+++ b/eval.c
@@ -21,19 +21,39 @@ typedef struct {
typedef struct Value {
ValueKind kind;
- ValueKind arr_kind;
+ union {
+ ValueKind arr_kind;
+ ValueKind ptr_kind;
+ };
union {
Integer intv;
UInteger uintv;
FloatVal floatv;
bool boolv;
char charv;
- struct Value *ptr;
+ void *ptr;
FnExpr *fn;
ArrVal arr;
};
} Value;
+size_t sizeof_val_kind(ValueKind k) {
+ Value v;
+ switch (k) {
+ case VAL_VOID:
+ return 0;
+ case VAL_INT: return sizeof v.intv;
+ case VAL_UINT: return sizeof v.uintv;
+ case VAL_FLOAT: return sizeof v.floatv;
+ case VAL_BOOL: return sizeof v.boolv;
+ case VAL_CHAR: return sizeof v.charv;
+ case VAL_PTR: return sizeof v.ptr;
+ case VAL_FN: return sizeof v.fn;
+ case VAL_ARR: return sizeof v.arr;
+ }
+ assert(0);
+ return 0;
+}
static ValueKind type_to_val_kind(Type *t) {
switch (t->kind) {
@@ -218,16 +238,13 @@ static bool val_cast(Location where, Value *out, Value cast, Type *type) {
out->charv = (char)cast.uintv; break;
case VAL_INT:
out->charv = (char)cast.intv; break;
- case VAL_FLOAT:
- out->charv = (char)cast.floatv; break;
case VAL_BOOL:
out->charv = cast.boolv ? 1 : 0; break;
- case VAL_FN:
- out->charv = (char)cast.fn; break;
- case VAL_PTR:
- out->charv = (char)cast.ptr; break;
case VAL_CHAR:
out->charv = cast.charv; break;
+ case VAL_FLOAT:
+ case VAL_FN:
+ case VAL_PTR:
case VAL_ARR:
case VAL_VOID: assert(0);
}
@@ -250,10 +267,52 @@ static bool val_cast(Location where, Value *out, Value cast, Type *type) {
case VAL_FLOAT:
case VAL_BOOL:
case VAL_ARR:
+ case VAL_VOID:
assert(0); return false;
- case VAL_VOID: assert(0);
}
break;
+ case TYPE_PTR:
+ out->kind = VAL_PTR;
+ out->ptr_kind = type_to_val_kind(type->ptr.of);
+ switch (cast.kind) {
+ case VAL_INT:
+ out->ptr = (void *)cast.intv; break;
+ case VAL_UINT:
+ out->ptr = (void *)cast.uintv; break;
+ case VAL_FN:
+ out->ptr = (void *)cast.fn; break;
+ case VAL_PTR:
+ out->ptr = cast.ptr; break;
+ case VAL_ARR:
+ out->ptr = cast.arr.data; break;
+ case VAL_CHAR:
+ case VAL_VOID:
+ case VAL_FLOAT:
+ case VAL_BOOL:
+ assert(0); return false;
+ }
+ return true;
+ case TYPE_ARR:
+ out->kind = VAL_ARR;
+ out->arr_kind = type_to_val_kind(type->arr.of);
+ out->arr.n = type->arr.n;
+ switch (cast.kind) {
+ case VAL_PTR:
+ out->arr.data = cast.ptr;
+ break;
+ case VAL_ARR:
+ out->arr.data = cast.arr.data;
+ break;
+ case VAL_FN:
+ case VAL_INT:
+ case VAL_UINT:
+ case VAL_CHAR:
+ case VAL_VOID:
+ case VAL_FLOAT:
+ case VAL_BOOL:
+ assert(0); return false;
+ }
+ return true;
case TYPE_TUPLE:
/* TODO: error at type checking */
assert(0);
@@ -320,10 +379,10 @@ static bool eval_expr(Expression *e, Value *v) {
break;
case EXPR_UNARY_OP: {
Expression *of_expr = e->unary.of;
+ Value of;
+ if (!eval_expr(of_expr, &of)) return false;
switch (e->unary.op) {
case UNARY_MINUS: {
- Value of;
- if (!eval_expr(of_expr, &of)) return false;
assert(e->type.kind == TYPE_BUILTIN);
v->kind = of.kind;
if (v->kind == VAL_INT) {
@@ -338,16 +397,70 @@ static bool eval_expr(Expression *e, Value *v) {
}
case UNARY_NOT:
v->kind = VAL_BOOL;
- v->boolv = !eval_truthiness(v);
+ v->boolv = !eval_truthiness(&of);
return true;
- case UNARY_ADDRESS:
+ case UNARY_ADDRESS: {
v->kind = VAL_PTR;
- v->ptr = err_malloc(sizeof *v->ptr); /* OPTIM */
- return eval_expr(e->unary.of, v->ptr);
+ get_ptr:
+ switch (of_expr->kind) {
+ case EXPR_UNARY_OP:
+ switch (of_expr->unary.op) {
+ case UNARY_DEREF:
+ /* &*x */
+ of_expr = of_expr->unary.of;
+ goto get_ptr;
+ default: assert(0); return false;
+ }
+ break;
+ case EXPR_IDENT:
+ err_print(e->where, "Cannot get address of identifiers at compile time yet.");
+ return false;
+ case EXPR_BINARY_OP:
+ switch (of_expr->binary.op) {
+ case BINARY_AT_INDEX: {
+ Expression *lhs_expr = of_expr->binary.lhs;
+ Expression *rhs_expr = of_expr->binary.rhs;
+ Value lhs, rhs;
+ if (!eval_expr(lhs_expr, &lhs)
+ || !eval_expr(rhs_expr, &rhs))
+ return false;
+ assert(lhs.kind == VAL_ARR && (rhs.kind == VAL_INT || rhs.kind == VAL_UINT));
+ v->ptr = (char *)lhs.arr.data + (Integer)sizeof_val_kind(lhs.arr_kind)
+ * (rhs.kind == VAL_INT ? rhs.intv : (Integer)rhs.uintv);
+ } break;
+ default: assert(0); return false;
+ }
+ break;
+
+ default: assert(0); return false;
+ }
+ } break;
case UNARY_DEREF: {
- Value ptr;
- if (!eval_expr(of_expr, &ptr)) return false;
- *v = *ptr.ptr;
+ v->kind = type_to_val_kind(&e->type);
+ switch (v->kind) {
+ case VAL_INT:
+ v->intv = *(Integer *)of.ptr; break;
+ case VAL_UINT:
+ v->uintv = *(UInteger *)of.ptr; break;
+ case VAL_FLOAT:
+ v->floatv = *(FloatVal *)of.ptr; break;
+ case VAL_BOOL:
+ v->boolv = *(bool *)of.ptr; break;
+ case VAL_CHAR:
+ v->charv = *(char *)of.ptr; break;
+ case VAL_ARR:
+ v->arr = *(ArrVal *)of.ptr; break;
+ case VAL_PTR:
+ v->ptr = *(void **)of.ptr; break;
+ case VAL_FN:
+ v->fn = *(FnExpr **)of.ptr; break;
+ case VAL_VOID:
+ assert(0); return false;
+ /* case VAL_INT: */
+ /* v->intv = *(Integer *)of.ptr; */
+ /* break; */
+
+ }
break;
} break;
case UNARY_DEL: /* TODO */
@@ -542,8 +655,8 @@ static bool eval_expr(Expression *e, Value *v) {
break;
case EXPR_NEW:
v->kind = VAL_PTR;
- v->ptr = err_calloc(1, sizeof *v->ptr); /* TODO(eventually): get this to work even if NULL ptrs aren't 0 */
- v->ptr->kind = type_to_val_kind(&e->new.type);
+ v->ptr_kind = type_to_val_kind(&e->new.type);
+ v->ptr = err_calloc(1, sizeof_val_kind(v->ptr_kind)); /* TODO(eventually): get this to work even if NULL ptrs aren't 0 */
break;
case EXPR_WHILE:
case EXPR_CALL:
diff --git a/main.c b/main.c
index aada098..596f3de 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
/*
TODO:
finish evaluator
+fix void fn type
re-do cgen
any odd number of "s for a string
*/
diff --git a/test.toc b/test.toc
index e963c8c..c8a03b4 100644
--- a/test.toc
+++ b/test.toc
@@ -1,15 +1,17 @@
main @= fn() {
- arr1 : ['a' as u8]int;
- arr2 : [main as u64]int;
- arr3 : [main as i64]int;
- N @= (-10 + (97 as char as f32)) as u32;
- arr4 : [N]int;
- arr5 : [main as u64]int;
- // arr6 : [main as u64 as fn() as u64]int;FIXME
- arr7 : [main as u64 as fn() int as u64]int;
+ // arr1 : ['a' as u8]int;
+ // arr2 : [main as u64]int;
+ // arr3 : [main as i64]int;
+ // N @= (-10 + (97 as char as f32)) as u32;
+ // arr4 : [N]int;
+ // arr5 : [main as u64]int;
+ // // arr6 : [main as u64 as fn() as u64]int;FIXME
+ // arr7 : [main as u64 as fn() int as u64]int;
- str @= "foo";
- arr8 : [(str[0] as u32) + (str[1] as u32) + (str[2] as u32)]int;
- asdf @= new int;
- arr9 : [asdf as u64]int;
+ // str @= "foo";
+ // arr8 : [(str[0] as u32) + (str[1] as u32) + (str[2] as u32)]int;
+ // asdf @= new int;
+ // arr9 : [asdf as u64]int;
+ // arr10 : [main as &i32 as u64]int;
+ arr11 : [((main as &u64) as [4]u64)[3]]int;
};
diff --git a/types.c b/types.c
index c8d2159..b277b8a 100644
--- a/types.c
+++ b/types.c
@@ -129,6 +129,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 */
switch (e->kind) {
case EXPR_IDENT: {
IdentDecl *id_decl = ident_decl(e->ident);
@@ -168,6 +169,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Type *t) {
if (!type_resolve(tr, &f->ret_type))
return false;
*ret_type = f->ret_type;
+ assert(f->params.item_sz == sizeof(Declaration));
arr_foreach(&f->params, Declaration, decl) {
if (!types_decl(tr, decl)) return false;
if (!type_resolve(tr, &decl->type))
@@ -677,6 +679,10 @@ static bool types_expr(Typer *tr, Expression *e) {
err_print(e->where, "Cannot take address of non-lvalue."); /* FEATURE: better err */
return false;
}
+ if (of_type->kind == TYPE_TUPLE) {
+ err_print(e->where, "Cannot take address of tuple.");
+ return false;
+ }
t->kind = TYPE_PTR;
t->ptr.of = err_malloc(sizeof *t->ptr.of); /* OPTIM */
*t->ptr.of = *of_type;