summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-24 14:00:55 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-24 14:00:55 -0400
commita87d34c7584c1c69faed8238def13331d56aa996 (patch)
treeac1ac615b9e128f3393e8e48cd3273d7bef089cd
parent6ed3d421006f7d56c5d96fbaf1b971bb3561d1ed (diff)
pointer arithmetic
-rw-r--r--eval.c39
-rw-r--r--main.c1
-rw-r--r--test.toc32
-rw-r--r--types.c55
4 files changed, 78 insertions, 49 deletions
diff --git a/eval.c b/eval.c
index fb79774..471d164 100644
--- a/eval.c
+++ b/eval.c
@@ -557,7 +557,9 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
eval_binary_bool_op_one(u32, U32, op); \
eval_binary_bool_op_one(u64, U64, op); \
eval_binary_bool_op_one(f32, F32, op); \
- eval_binary_bool_op_one(f64, F64, op);
+ eval_binary_bool_op_one(f64, F64, op); \
+ eval_binary_bool_op_one(boolv, BOOL, op); \
+ eval_binary_bool_op_one(charv, CHAR, op);
#define eval_binary_bool_op_nums_only(op) \
{Type *ltype=&e->binary.lhs->type, \
@@ -566,14 +568,17 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
rtype : ltype; \
val_cast(&lhs, ltype, &lhs, cast_to); \
val_cast(&rhs, rtype, &rhs, cast_to); \
- assert(e->type.kind == TYPE_BUILTIN); \
+ assert(e->binary.lhs->type.kind == TYPE_BUILTIN); \
switch (builtin) { \
eval_binary_bool_op_nums(builtin, op); \
default:printf("%d\n",(int)builtin); \
assert(!"Invalid builtin to "#op); break; \
}}
-
+#define eval_binary_bool_op(op) \
+ if (e->binary.lhs->type.kind == TYPE_PTR) \
+ v->boolv = lhs.ptr op rhs.ptr; \
+ else { eval_binary_bool_op_nums_only(op); }
switch (e->kind) {
case EXPR_UNARY_OP: {
@@ -652,25 +657,37 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
BuiltinType builtin = e->binary.lhs->type.builtin;
switch (e->binary.op) {
case BINARY_ADD:
- eval_binary_op_nums_only(+); break;
+ if (e->binary.lhs->type.kind == TYPE_PTR) {
+ v->ptr = (char *)lhs.ptr + val_to_i64(&rhs, e->binary.rhs->type.builtin)
+ * (I64)compiler_sizeof(e->binary.lhs->type.ptr);
+ } else {
+ eval_binary_op_nums_only(+);
+ }
+ break;
case BINARY_SUB:
- eval_binary_op_nums_only(-); break;
+ if (e->binary.lhs->type.kind == TYPE_PTR) {
+ v->ptr = (char *)lhs.ptr - val_to_i64(&rhs, e->binary.rhs->type.builtin)
+ * (I64)compiler_sizeof(e->binary.lhs->type.ptr);
+ } else {
+ eval_binary_op_nums_only(-);
+ }
+ break;
case BINARY_MUL:
eval_binary_op_nums_only(*); break;
case BINARY_DIV:
eval_binary_op_nums_only(/); break;
case BINARY_LT:
- eval_binary_bool_op_nums_only(<); break;
+ eval_binary_bool_op(<); break;
case BINARY_LE:
- eval_binary_bool_op_nums_only(<=); break;
+ eval_binary_bool_op(<=); break;
case BINARY_GT:
- eval_binary_bool_op_nums_only(>); break;
+ eval_binary_bool_op(>); break;
case BINARY_GE:
- eval_binary_bool_op_nums_only(>=); break;
+ eval_binary_bool_op(>=); break;
case BINARY_EQ:
- eval_binary_bool_op_nums_only(==); break;
+ eval_binary_bool_op(==); break;
case BINARY_NE:
- eval_binary_bool_op_nums_only(!=); break;
+ eval_binary_bool_op(!=); break;
case BINARY_SET:
if (!eval_set(ev, e->binary.lhs, &rhs)) return false;
break;
diff --git a/main.c b/main.c
index aafdd19..1b8e48e 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
TODO:
-bf interpreter (& other tests)
pointer arithmetic
compile time arrays, slices
unicode variable names
diff --git a/test.toc b/test.toc
index 71545c6..48e0e1e 100644
--- a/test.toc
+++ b/test.toc
@@ -13,28 +13,30 @@ putf @= fn(x: float) {
");
};
-foo @= fn() int {
- N := 10;
+sum @= fn(x: []int, n: int) int {
+ p := &x[0];
+ end := &x[n-1];
+ total := 0;
+ while p <= end {
+ total = total + *p;
+ p = p + 1;
+ }
+ total
+};
+
+f @= fn() int {
+ N @= 10;
+
numbers := new(int, N);
i := 0;
while i < N {
numbers[i] = i;
i = i + 1;
}
- numbers[5:7][1] + numbers[2:][0] + numbers[:6][3]
+ sum(numbers, N)
};
main @= fn() {
- N @= 5;
- puti(N);
- x : [foo()]int;
- puti(foo());
- teststr := "Hello!";
- i := 0;
- while i < 5 {
- putch(teststr[i]);
- i = i + 1;
- }
- y:int=5+#C("(1<<3)");
- puti(y);
+ a: [f()]int;
+ puti(f());
};
diff --git a/types.c b/types.c
index ac56693..d93770f 100644
--- a/types.c
+++ b/types.c
@@ -33,7 +33,9 @@ static bool type_eq(Type *a, Type *b) {
return type_builtin_is_numerical(b->builtin);
}
if (b->flags & TYPE_FLAG_FLEXIBLE) {
- return type_eq(b, a); /* OPTIM? */
+ Type *tmp = a;
+ a = b;
+ b = tmp;
}
switch (a->kind) {
case TYPE_VOID: return true;
@@ -152,12 +154,6 @@ static bool expr_must_lval(Expression *e) {
info_print(d->where, "%s was declared here.", istr);
return false;
}
- if (d->flags & DECL_FLAG_PARAM) {
- char *istr = ident_to_str(e->ident);
- err_print(e->where, "You cannot modify or take the address of a parameter (%s).", istr);
- return false;
- }
-
return true;
}
case EXPR_UNARY_OP:
@@ -165,7 +161,7 @@ static bool expr_must_lval(Expression *e) {
break;
case EXPR_BINARY_OP:
switch (e->binary.op) {
- case BINARY_AT_INDEX: return expr_arr_must_mut(e->binary.lhs);
+ case BINARY_AT_INDEX: return true;
default: break;
}
break;
@@ -917,24 +913,39 @@ static bool types_expr(Typer *tr, Expression *e) {
case BINARY_GE:
case BINARY_EQ:
case BINARY_NE: {
- bool valid = true;
- if (e->binary.op != BINARY_SET) {
+ BinaryOp o = e->binary.op;
+ bool valid = false;
+ if (o == BINARY_SET) {
+ valid = type_eq(lhs_type, rhs_type);
+ } else {
/* numerical binary ops */
- if (lhs_type->kind != rhs_type->kind) {
- valid = false;
- } else if (lhs_type->kind != TYPE_BUILTIN) {
- valid = false;
- } else {
- if (e->binary.op == BINARY_EQ || e->binary.op == BINARY_NE) {
- } else if (!type_builtin_is_numerical(lhs_type->builtin) || !type_builtin_is_numerical(rhs_type->builtin)) {
- valid = false;
+ if (lhs_type->kind == rhs_type->kind && lhs_type->kind == TYPE_BUILTIN
+ && type_builtin_is_numerical(lhs_type->builtin) && lhs_type->builtin == rhs_type->builtin) {
+ valid = true;
+ }
+ if (o == BINARY_ADD || o == BINARY_SUB) {
+ if (lhs_type->kind == TYPE_PTR &&
+ rhs_type->kind == TYPE_BUILTIN &&
+ type_builtin_is_numerical(rhs_type->builtin)) {
+ valid = true;
+ }
+ }
+ if (o == BINARY_LT || o == BINARY_GT || o == BINARY_LE || o == BINARY_GE
+ || o == BINARY_EQ || o == BINARY_NE) {
+ /* comparable types */
+ if (type_eq(lhs_type, rhs_type)) {
+ switch (lhs_type->kind) {
+ case TYPE_PTR:
+ case TYPE_BUILTIN: /* all builtins are comparable */
+ valid = true;
+ default:
+ break;
+ }
}
}
-
}
- if (!type_eq(lhs_type, rhs_type)) valid = false;
if (valid) {
- switch (e->binary.op) {
+ switch (o) {
case BINARY_SET:
/* type of x = y is always void */
t->kind = TYPE_VOID;
@@ -973,7 +984,7 @@ static bool types_expr(Typer *tr, Expression *e) {
char *s1, *s2;
s1 = type_to_str(lhs_type);
s2 = type_to_str(rhs_type);
- const char *op = binary_op_to_str(e->binary.op);
+ const char *op = binary_op_to_str(o);
err_print(e->where, "Invalid types to operator %s: %s and %s", op, s1, s2);
return false;
}