summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c91
-rw-r--r--eval.c113
-rw-r--r--main.c3
-rw-r--r--parse.c25
-rwxr-xr-xrunv4
-rw-r--r--test.toc23
-rw-r--r--tokenizer.c4
-rw-r--r--types.c12
-rw-r--r--types.h16
9 files changed, 153 insertions, 138 deletions
diff --git a/cgen.c b/cgen.c
index a04319c..269f276 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1661,14 +1661,15 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
} break;
case STMT_FOR: {
For *fo = s->for_;
- int is_range = fo->flags & FOR_IS_RANGE;
+ ForFlags flags = fo->flags;
+ U32 is_range = flags & FOR_IS_RANGE;
Declaration *header_decl = &fo->header;
Identifier val_ident = header_decl->idents[0];
Identifier index_ident = header_decl->idents[1];
Type *fo_type = &header_decl->type;
assert(fo_type->kind == TYPE_TUPLE && arr_len(fo_type->tuple) == 2);
Type *val_type = &fo_type->tuple[0];
- Type *index_type = &fo_type->tuple[1];
+ assert(type_is_builtin(&fo_type->tuple[1], BUILTIN_I64)); /* index type is always int */
bool has_val = !ident_eq_str(val_ident, "_");
bool has_index = !ident_eq_str(index_ident, "_");
@@ -1746,16 +1747,50 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
}
if (has_index) {
- cgen_type_pre(g, index_type);
- cgen_write(g, " ");
+ cgen_write(g, "i64 ");
cgen_ident(g, index_ident);
- cgen_type_post(g, index_type); /* not needed yet, but keeping it here to prevent potential future problems */
cgen_write(g, " = 0; ");
}
cgen_write(g, "for (");
-
- if (!is_range) {
+ if (is_range) {
+ bool positive_step
+ = fo->range.stepval == NULL || val_is_nonnegative(*fo->range.stepval, val_type);
+ if (!(flags & FOR_INCLUDES_FROM)) {
+ if (has_val)
+ cgen_ident(g, val_ident);
+ else
+ cgen_write(g, "val_");
+ cgen_write(g, " += ");
+ if (fo->range.stepval) {
+ cgen_val(g, fo->range.stepval, val_type);
+ } else {
+ cgen_write(g, "1");
+ }
+ }
+ cgen_write(g, "; ");
+ if (fo->range.to) { /* if finite */
+ if (has_val)
+ cgen_ident(g, val_ident);
+ else
+ cgen_write(g, "val_");
+ cgen_write(g, " %c%s to_; ", positive_step ? '<' : '>', (flags & FOR_INCLUDES_TO) ? "=" : "");
+ }
+ if (fo->range.stepval) {
+ cgen_val_pre(g, fo->range.stepval, val_type);
+ }
+ if (has_val)
+ cgen_ident(g, val_ident);
+ else
+ cgen_write(g, "val_");
+ cgen_write(g, " += ");
+ if (fo->range.stepval) {
+ cgen_val(g, fo->range.stepval, val_type);
+ } else {
+ cgen_write(g, "1");
+ }
+ if (has_index) { cgen_write(g, ", ++"); cgen_ident(g, index_ident); }
+ } else {
cgen_type_pre(g, val_type);
cgen_write(g, "(%sp_)", uses_ptr ? "" : "*");
cgen_type_post(g, val_type);
@@ -1779,46 +1814,10 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
break;
default: assert(0); break;
}
+ cgen_write(g, "; p_ != end_; ++p_");
+ if (has_index) { cgen_write(g, ", ++"); cgen_ident(g, index_ident); }
}
-
- cgen_write(g, "; ");
- if (!(is_range && !fo->range.to)) { /* if it's finite */
- if (is_range) {
- if (has_val)
- cgen_ident(g, val_ident);
- else
- cgen_write(g, "val_");
- bool positive_step
- = fo->range.stepval == NULL || val_is_nonnegative(*fo->range.stepval, val_type);
- cgen_write(g, " %c= to_", positive_step ? '<' : '>');
- } else {
- cgen_write(g, "p_ != end_");
- }
- }
- cgen_write(g, "; ");
- if (is_range) {
- if (fo->range.stepval) {
- cgen_val_pre(g, fo->range.stepval, val_type);
- }
- if (has_val)
- cgen_ident(g, val_ident);
- else
- cgen_write(g, "val_");
- cgen_write(g, " += ");
- if (fo->range.stepval) {
- cgen_val(g, fo->range.stepval, val_type);
- } else {
- cgen_write(g, "1");
- }
- if (has_index) cgen_write(g, ", ");
- } else {
- cgen_write(g, "++p_");
- if (has_index) cgen_write(g, ", ");
- }
- if (has_index) {
- cgen_write(g, "++");
- cgen_ident(g, index_ident);
- }
+
cgen_write(g, ") {");
cgen_nl(g);
if (has_val) {
diff --git a/eval.c b/eval.c
index 2b65637..b6f36b7 100644
--- a/eval.c
+++ b/eval.c
@@ -300,35 +300,35 @@ static inline void val_free_ptr(Value *v, Type *t) {
#define builtin_casts_to_int(x) \
case BUILTIN_I8: \
- vout->i8 = (I8)(I64)vin->x; break; \
+ vout->i8 = (I8)(I64)vin.x; break; \
case BUILTIN_I16: \
- vout->i16 = (I16)(I64)vin->x; break; \
+ vout->i16 = (I16)(I64)vin.x; break; \
case BUILTIN_I32: \
- vout->i32 = (I32)(I64)vin->x; break; \
+ vout->i32 = (I32)(I64)vin.x; break; \
case BUILTIN_I64: \
- vout->i64 = (I64)vin->x; break; \
+ vout->i64 = (I64)vin.x; break; \
case BUILTIN_U8: \
- vout->u8 = (U8)(U64)vin->x; break; \
+ vout->u8 = (U8)(U64)vin.x; break; \
case BUILTIN_U16: \
- vout->u16 = (U16)(U64)vin->x; break; \
+ vout->u16 = (U16)(U64)vin.x; break; \
case BUILTIN_U32: \
- vout->u32 = (U32)(U64)vin->x; break; \
+ vout->u32 = (U32)(U64)vin.x; break; \
case BUILTIN_U64: \
- vout->u64 = (U64)vin->x; break
+ vout->u64 = (U64)vin.x; break
#define builtin_casts_to_num(x) \
builtin_casts_to_int(x); \
case BUILTIN_F32: \
- vout->f32 = (F32)vin->x; break; \
+ vout->f32 = (F32)vin.x; break; \
case BUILTIN_F64: \
- vout->f64 = (F64)vin->x; break
+ vout->f64 = (F64)vin.x; break
#define builtin_int_casts(low, up) \
case BUILTIN_##up: \
switch (to) { \
builtin_casts_to_num(low); \
- case BUILTIN_CHAR: vout->charv = (char)vin->low; break; \
- case BUILTIN_BOOL: vout->boolv = vin->low != 0; break; \
+ case BUILTIN_CHAR: vout->charv = (char)vin.low; break; \
+ case BUILTIN_BOOL: vout->boolv = vin.low != 0; break; \
case BUILTIN_NMS: \
case BUILTIN_VOID: \
case BUILTIN_TYPE: \
@@ -340,7 +340,7 @@ static inline void val_free_ptr(Value *v, Type *t) {
case BUILTIN_##up: \
switch (to) { \
builtin_casts_to_num(low); \
- case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break; \
+ case BUILTIN_BOOL: vout->boolv = vin.low != 0.0f; break; \
case BUILTIN_CHAR: \
case BUILTIN_TYPE: \
case BUILTIN_NMS: \
@@ -349,9 +349,9 @@ static inline void val_free_ptr(Value *v, Type *t) {
assert(0); break; \
} break
-static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinType to) {
+static void val_builtin_cast(Value vin, BuiltinType from, Value *vout, BuiltinType to) {
if (from == to) {
- *vout = *vin;
+ *vout = vin;
return;
}
switch (from) {
@@ -366,7 +366,7 @@ static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinT
builtin_float_casts(f32, F32);
builtin_float_casts(f64, F64);
- case BUILTIN_BOOL: vout->boolv = builtin_truthiness(*vin, from); break;
+ case BUILTIN_BOOL: vout->boolv = builtin_truthiness(vin, from); break;
case BUILTIN_CHAR:
switch (to) {
builtin_casts_to_int(charv);
@@ -390,12 +390,12 @@ static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinT
}
}
-static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
+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);
+ vout->boolv = val_truthiness(vin, from);
return;
}
@@ -412,14 +412,14 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
break;
case TYPE_PTR:
switch (from->builtin) {
- case BUILTIN_I8: vout->ptr = (void *)(U64)vin->i8; break;
- case BUILTIN_I16: vout->ptr = (void *)(U64)vin->i16; break;
- case BUILTIN_I32: vout->ptr = (void *)(U64)vin->i32; break;
- case BUILTIN_I64: vout->ptr = (void *)(U64)vin->i64; break;
- case BUILTIN_U8: vout->ptr = (void *)(U64)vin->u8; break;
- case BUILTIN_U16: vout->ptr = (void *)(U64)vin->u16; break;
- case BUILTIN_U32: vout->ptr = (void *)(U64)vin->u32; break;
- case BUILTIN_U64: vout->ptr = (void *)(U64)vin->u64; break;
+ case BUILTIN_I8: vout->ptr = (void *)(U64)vin.i8; break;
+ case BUILTIN_I16: vout->ptr = (void *)(U64)vin.i16; break;
+ case BUILTIN_I32: vout->ptr = (void *)(U64)vin.i32; break;
+ case BUILTIN_I64: vout->ptr = (void *)(U64)vin.i64; break;
+ case BUILTIN_U8: vout->ptr = (void *)(U64)vin.u8; break;
+ case BUILTIN_U16: vout->ptr = (void *)(U64)vin.u16; break;
+ case BUILTIN_U32: vout->ptr = (void *)(U64)vin.u32; break;
+ case BUILTIN_U64: vout->ptr = (void *)(U64)vin.u64; break;
default: assert(0); break;
}
break;
@@ -438,10 +438,10 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_FN:
switch (to->kind) {
case TYPE_PTR:
- vout->ptr = (void *)vin->fn;
+ vout->ptr = (void *)vin.fn;
break;
case TYPE_FN:
- vout->fn = vin->fn;
+ vout->fn = vin.fn;
break;
default:
assert(0); break;
@@ -465,13 +465,13 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
}
break;
case TYPE_ARR:
- vout->arr = vin->ptr;
+ vout->arr = vin.ptr;
break;
case TYPE_PTR:
- vout->ptr = vin->ptr;
+ vout->ptr = vin.ptr;
break;
case TYPE_FN:
- vout->fn = vin->ptr;
+ vout->fn = vin.ptr;
break;
default:
assert(0);
@@ -482,10 +482,10 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_ARR:
switch (to->kind) {
case TYPE_PTR:
- vout->ptr = vin->arr;
+ vout->ptr = vin.arr;
break;
case TYPE_ARR:
- vout->arr = vin->arr;
+ vout->arr = vin.arr;
break;
default:
assert(0); break;
@@ -494,13 +494,13 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_SLICE:
switch (to->kind) {
case TYPE_PTR:
- vout->ptr = vin->slice.data;
+ vout->ptr = vin.slice.data;
break;
case TYPE_ARR:
- vout->arr = vin->slice.data;
+ vout->arr = vin.slice.data;
break;
case TYPE_SLICE:
- vout->slice = vin->slice;
+ vout->slice = vin.slice;
break;
default:
assert(0); break;
@@ -858,6 +858,7 @@ static Status eval_set(Evaluator *ev, Expression *set, Value *to) {
return true;
}
+/* @TODO(eventually): this could probably be made better */
static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value rhs, Type *rhs_type, Value *out, Type *out_type) {
/* WARNING: macros ahead */
@@ -888,8 +889,8 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
#define eval_binary_op_nums_only(op) \
- val_cast(&lhs, lhs_type, &lhs, out_type); \
- val_cast(&rhs, rhs_type, &rhs, out_type); \
+ val_cast(lhs, lhs_type, &lhs, out_type); \
+ val_cast(rhs, rhs_type, &rhs, out_type); \
assert(out_type->kind == TYPE_BUILTIN); \
switch (builtin) { \
eval_binary_op_nums(builtin, op); \
@@ -897,8 +898,8 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
}
#define eval_binary_op_ints_only(op) \
- val_cast(&lhs, lhs_type, &lhs, out_type); \
- val_cast(&rhs, rhs_type, &rhs, out_type); \
+ val_cast(lhs, lhs_type, &lhs, out_type); \
+ val_cast(rhs, rhs_type, &rhs, out_type); \
assert(out_type->kind == TYPE_BUILTIN); \
switch (builtin) { \
eval_binary_op_ints(builtin, op); \
@@ -927,8 +928,8 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
#define eval_binary_bool_op_nums_only(op) \
{Type *cast_to = lhs_type->flags & TYPE_IS_FLEXIBLE ? \
rhs_type : lhs_type; \
- val_cast(&lhs, lhs_type, &lhs, cast_to); \
- val_cast(&rhs, rhs_type, &rhs, cast_to); \
+ val_cast(lhs, lhs_type, &lhs, cast_to); \
+ val_cast(rhs, rhs_type, &rhs, cast_to); \
assert(lhs_type->kind == TYPE_BUILTIN); \
switch (cast_to->builtin) { \
eval_binary_bool_op_nums(builtin, op); \
@@ -954,11 +955,11 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
case BINARY_SUB:
if (lhs_type->kind == TYPE_PTR) {
if (rhs_type->kind == TYPE_PTR) {
- out->i64 = (I64)((char *)rhs.ptr - (char *)lhs.ptr) / (I64)compiler_sizeof(lhs_type);
-
+ out->i64 = (I64)((char *)lhs.ptr - (char *)rhs.ptr) / (I64)compiler_sizeof(lhs_type->ptr);
+ } else {
+ out->ptr = (char *)lhs.ptr - val_to_i64(rhs, rhs_type->builtin)
+ * (I64)compiler_sizeof(lhs_type->ptr);
}
- out->ptr = (char *)lhs.ptr - val_to_i64(rhs, rhs_type->builtin)
- * (I64)compiler_sizeof(lhs_type->ptr);
} else {
eval_binary_op_nums_only(-);
}
@@ -1235,7 +1236,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
case EXPR_CAST: {
Value casted;
if (!eval_expr(ev, e->cast.expr, &casted)) return false;
- val_cast(&casted, &e->cast.expr->type, v, &e->cast.type);
+ val_cast(casted, &e->cast.expr->type, v, &e->cast.type);
} break;
case EXPR_FN:
v->fn = e->fn;
@@ -1609,7 +1610,9 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
Value *value_val = &for_val_tuple[0];
Value *index_val = &for_val_tuple[1];
Type *value_type = &header->type.tuple[0];
- if (fo->flags & FOR_IS_RANGE) {
+ ForFlags flags = fo->flags;
+
+ if (flags & FOR_IS_RANGE) {
assert(value_type->kind == TYPE_BUILTIN);
Value from, to;
Value stepval;
@@ -1618,9 +1621,19 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
if (fo->range.to && !eval_expr(ev, fo->range.to, &to)) return false;
if (fo->range.stepval)
stepval = *fo->range.stepval;
- Value x = from;
+ Value x;
+ val_cast(from, &fo->range.from->type, &x, value_type);
bool step_is_negative = fo->range.stepval && !val_is_nonnegative(stepval, value_type);
if (index_val) index_val->i64 = 0;
+ BinaryOp compare_binop;
+ if (flags & FOR_INCLUDES_TO) {
+ compare_binop = step_is_negative ? BINARY_GE : BINARY_LE;
+ } else {
+ compare_binop = step_is_negative ? BINARY_GT : BINARY_LT;
+ }
+ if (!(flags & FOR_INCLUDES_FROM)) {
+ eval_numerical_bin_op(x, value_type, BINARY_ADD, stepval, value_type, &x, value_type);
+ }
while (1) {
if (fo->range.to) {
/* check if loop has ended */
@@ -1632,7 +1645,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
boolt.builtin = BUILTIN_BOOL;
Value cont;
- eval_numerical_bin_op(lhs, value_type, step_is_negative ? BINARY_GE : BINARY_LE, rhs, &fo->range.to->type, &cont, &boolt);
+ eval_numerical_bin_op(lhs, value_type, compare_binop, rhs, &fo->range.to->type, &cont, &boolt);
if (!cont.boolv) break;
}
if (value_val) *value_val = x;
diff --git a/main.c b/main.c
index 1dfcb25..3e06c41 100644
--- a/main.c
+++ b/main.c
@@ -8,11 +8,10 @@
/*
@TODO:
-a..b should probably only go up to b-1
figure out how printf is gonna work
if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared)
fix #foreign not at global scope - right now the cgen'd definition doesn't use the proper type
-find out why file output is really slow at compile time; try to improve it
+find out why loop with file output is really slow at compile time; try to improve it
improve type_to_str:
Foo ::= struct(t::Type) {}
type_to_str(Foo(int))
diff --git a/parse.c b/parse.c
index b723db0..836e675 100644
--- a/parse.c
+++ b/parse.c
@@ -430,6 +430,9 @@ static Token *expr_find_end(Parser *p, ExprEndFlags flags) {
return token;
break;
case KW_DOTDOT:
+ case KW_DOTCOMMA:
+ case KW_COMMADOT:
+ case KW_COMMACOMMA:
if (all_levels_0 && (flags & EXPR_CAN_END_WITH_DOTDOT))
return token;
break;
@@ -2212,6 +2215,10 @@ static bool is_decl(Tokenizer *t) {
}
}
+static bool is_for_range_separator(Keyword kw) {
+ return kw == KW_DOTDOT || kw == KW_DOTCOMMA || kw == KW_COMMADOT || kw == KW_COMMACOMMA;
+}
+
/* sets *was_a_statement to false if s was not filled, but the token was advanced */
static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
Tokenizer *t = p->tokr;
@@ -2417,7 +2424,8 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
goto for_fail;
if (token_is_kw(first_end, KW_LBRACE)) {
fo->of = first;
- } else if (token_is_kw(first_end, KW_DOTDOT) || token_is_kw(first_end, KW_COMMA)) {
+ } else if (first_end->kind == TOKEN_KW &&
+ (is_for_range_separator(first_end->kw) || first_end->kw == KW_COMMA)) {
fo->flags |= FOR_IS_RANGE;
fo->range.from = first;
if (token_is_kw(first_end, KW_COMMA)) {
@@ -2425,16 +2433,23 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
++t->token;
fo->range.step = parser_new_expr(p);
Token *step_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE|EXPR_CAN_END_WITH_DOTDOT);
- if (!parse_expr(p, fo->range.step, step_end))
- goto for_fail;
- if (!token_is_kw(step_end, KW_DOTDOT)) {
- err_print(token_location(p->file, step_end), "Expected .. to follow step in for statement.");
+ if (step_end->kind != TOKEN_KW || !is_for_range_separator(step_end->kw)) {
+ err_print(token_location(p->file, step_end), "Expected .. / ., / ,. / ,, to follow step in for statement.");
tokr_skip_to_eof(t);
goto for_fail;
}
+ if (!parse_expr(p, fo->range.step, step_end))
+ goto for_fail;
} else {
fo->range.step = NULL;
}
+ {
+ Keyword separator = t->token->kw;
+ if (separator == KW_DOTDOT || separator == KW_DOTCOMMA)
+ fo->flags |= FOR_INCLUDES_FROM;
+ if (separator == KW_DOTDOT || separator == KW_COMMADOT)
+ fo->flags |= FOR_INCLUDES_TO;
+ }
++t->token; /* move past .. */
if (token_is_kw(t->token, KW_LBRACE)) {
fo->range.to = NULL; /* infinite loop! */
diff --git a/runv b/runv
index 4134417..8cba96a 100755
--- a/runv
+++ b/runv
@@ -12,8 +12,8 @@ fi
valgrind $FLAGS --track-origins=yes --exit-on-first-error=yes --error-exitcode=1 --malloc-fill=0xcd --free-fill=0xef --num-callers=100 ./toc $tocf || exit 1
if [ "$1" = "c" ]; then
- gcc out.c -g -Wno-builtin-declaration-mismatch && ./a.out
+ ./test
elif [ "$1" = "pc" ]; then
- cat out.c
+ cat test.c
fi
rm vgcore* 2> /dev/null
diff --git a/test.toc b/test.toc
index ca114ec..536cf34 100644
--- a/test.toc
+++ b/test.toc
@@ -2,25 +2,8 @@
#include "std/mem.toc";
main ::= fn() {
- n := 100000000;
- sieve := news(bool, n);
- sieve[0] = true;
- sieve[1] = true;
- i := 0;
- while i*i <= n {
- defer i += 1;
- if sieve[i] { continue; }
- j := 2*i;
- while j < n {
- sieve[j] = true;
- j += i;
- }
+ for i, v : (float, int) = 10,-1,.0 {
+ io.puti(i as int);
}
- total := 0;
- for is_composite, i := sieve {
- if !is_composite {
- total += i;
- }
- }
- io.puti(total);
}
+main();
diff --git a/tokenizer.c b/tokenizer.c
index 3f83e6f..d384da2 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -387,8 +387,8 @@ static Status tokenize_file(Tokenizer *t, File *file) {
}
while (1) {
if (*t->s == '.') {
- if (t->s[1] == '.') {
- /* .. (not a decimal point; end the number here) */
+ if (!isdigit(t->s[1])) {
+ /* not a decimal point; end the number here (could be .. or .,) */
break;
}
if (token->kind == TOKEN_LITERAL_FLOAT) {
diff --git a/types.c b/types.c
index 01a5c50..956ff4a 100644
--- a/types.c
+++ b/types.c
@@ -8,7 +8,7 @@ static Status types_block(Typer *tr, Block *b);
static Status types_decl(Typer *tr, Declaration *d);
static Status type_resolve(Typer *tr, Type *t, Location where);
static Status eval_expr(Evaluator *ev, Expression *e, Value *v);
-static void val_cast(Value *vin, Type *from, Value *vout, Type *to);
+static void val_cast(Value vin, Type *from, Value *vout, Type *to);
static U64 val_to_u64(Value v, BuiltinType v_type);
static I64 val_to_i64(Value v, BuiltinType v_type);
static bool val_truthiness(Value v, Type *t);
@@ -660,7 +660,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
if (param->expr.type.flags & TYPE_IS_FLEXIBLE) {
/* cast to the annotated type, if one exists */
if (param->flags & DECL_ANNOTATES_TYPE) {
- val_cast(&param->expr.val, &param->expr.type, &param->expr.val, &param->type);
+ val_cast(param->expr.val, &param->expr.type, &param->expr.val, &param->type);
param->expr.type = param->type;
}
}
@@ -3384,10 +3384,10 @@ top:
index_type = &fo_type_tuple[1];
assert(val_type->flags & TYPE_IS_RESOLVED);
assert(index_type->flags & TYPE_IS_RESOLVED);
- if (!type_is_int(index_type)) {
+ if (!type_is_builtin(index_type, BUILTIN_I64)) {
char *str = type_to_str(index_type);
- err_print(header->where, "Expected index type of for loop to be a builtin integer type, but it's %s.", str);
- free(s);
+ err_print(header->where, "Expected index type of for loop to be type int, but it's %s.", str);
+ free(str);
goto for_fail;
}
} else {
@@ -3485,7 +3485,7 @@ top:
info_print(fo->range.step->where, "Note that the step of a for loop must be a compile-time constant.");
goto for_fail;
}
- val_cast(stepval, &fo->range.step->type, stepval, val_type);
+ val_cast(*stepval, &fo->range.step->type, stepval, val_type);
fo->range.stepval = stepval;
}
} else {
diff --git a/types.h b/types.h
index bfbec3c..8ffd890 100644
--- a/types.h
+++ b/types.h
@@ -250,7 +250,6 @@ static const char *directives[DIRECT_COUNT] = {
typedef enum {
KW_SEMICOLON,
KW_COLON,
- KW_COMMA,
KW_LPAREN,
KW_RPAREN,
KW_LBRACE,
@@ -278,6 +277,10 @@ typedef enum {
KW_SLASH,
KW_PERCENT,
KW_DOTDOT,
+ KW_DOTCOMMA,
+ KW_COMMADOT,
+ KW_COMMACOMMA,
+ KW_COMMA,
KW_DOT,
KW_EQ,
KW_LAST_SYMBOL = KW_EQ, /* last one entirely consisting of symbols */
@@ -322,10 +325,10 @@ typedef enum {
} Keyword;
static const char *const keywords[KW_COUNT] = {
- ";", ":", ",", "(", ")", "{", "}", "[", "]", "==",
+ ";", ":", "(", ")", "{", "}", "[", "]", "==",
"+=", "-=", "*=", "/=", "%=",
"!=", "<=", "<", ">=", ">", "&&", "||",
- "+", "-", "*", "!", "&", "/", "%", "..", ".",
+ "+", "-", "*", "!", "&", "/", "%", "..", ".,", ",.", ",,", ",", ".",
"=",
"if", "elif", "else", "while", "for", "return", "break",
"continue", "defer", "fn", "as", "struct",
@@ -864,10 +867,13 @@ typedef struct While {
} While;
enum {
- FOR_IS_RANGE = 0x01
+ FOR_IS_RANGE = 0x01,
+ FOR_INCLUDES_FROM = 0x02,
+ FOR_INCLUDES_TO = 0x04
};
+typedef U8 ForFlags;
typedef struct For {
- U8 flags;
+ ForFlags flags;
Declaration header;
Block body;
union {