diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-24 14:00:55 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-24 14:00:55 -0400 |
commit | a87d34c7584c1c69faed8238def13331d56aa996 (patch) | |
tree | ac1ac615b9e128f3393e8e48cd3273d7bef089cd | |
parent | 6ed3d421006f7d56c5d96fbaf1b971bb3561d1ed (diff) |
pointer arithmetic
-rw-r--r-- | eval.c | 39 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 32 | ||||
-rw-r--r-- | types.c | 55 |
4 files changed, 78 insertions, 49 deletions
@@ -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; @@ -1,6 +1,5 @@ /* TODO: -bf interpreter (& other tests) pointer arithmetic compile time arrays, slices unicode variable names @@ -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()); }; @@ -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; } |