summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c44
-rw-r--r--main.c1
-rw-r--r--parse.c14
-rw-r--r--test.toc71
-rw-r--r--types.c35
-rw-r--r--types.h8
6 files changed, 82 insertions, 91 deletions
diff --git a/eval.c b/eval.c
index df2c3c6..7d90c5f 100644
--- a/eval.c
+++ b/eval.c
@@ -26,20 +26,20 @@ static inline void *evalr_calloc(Evaluator *ev, size_t n, size_t bytes) {
return allocr_calloc(ev->allocr, n, bytes);
}
-static bool builtin_truthiness(Value *v, BuiltinType b) {
+static bool builtin_truthiness(Value v, BuiltinType b) {
switch (b) {
- case BUILTIN_I8: return v->i8 != 0;
- case BUILTIN_I16: return v->i16 != 0;
- case BUILTIN_I32: return v->i32 != 0;
- case BUILTIN_I64: return v->i64 != 0;
- case BUILTIN_U8: return v->u8 != 0;
- case BUILTIN_U16: return v->u16 != 0;
- case BUILTIN_U32: return v->u32 != 0;
- case BUILTIN_U64: return v->u64 != 0;
- case BUILTIN_F32: return v->f32 != 0;
- case BUILTIN_F64: return v->f64 != 0;
- case BUILTIN_BOOL: return v->boolv;
- case BUILTIN_CHAR: return v->charv != 0;
+ case BUILTIN_I8: return v.i8 != 0;
+ case BUILTIN_I16: return v.i16 != 0;
+ case BUILTIN_I32: return v.i32 != 0;
+ case BUILTIN_I64: return v.i64 != 0;
+ case BUILTIN_U8: return v.u8 != 0;
+ case BUILTIN_U16: return v.u16 != 0;
+ case BUILTIN_U32: return v.u32 != 0;
+ case BUILTIN_U64: return v.u64 != 0;
+ case BUILTIN_F32: return v.f32 != 0;
+ case BUILTIN_F64: return v.f64 != 0;
+ case BUILTIN_BOOL: return v.boolv;
+ case BUILTIN_CHAR: return v.charv != 0;
case BUILTIN_TYPE:
case BUILTIN_NMS:
break;
@@ -47,16 +47,16 @@ static bool builtin_truthiness(Value *v, BuiltinType b) {
assert(0); return false;
}
-static bool val_truthiness(Value *v, Type *t) {
+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;
case TYPE_BUILTIN: return builtin_truthiness(v, t->builtin);
- case TYPE_PTR: return v->ptr != NULL;
- case TYPE_FN: return v->fn != NULL;
+ case TYPE_PTR: return v.ptr != NULL;
+ 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_SLICE: return v.slice.n > 0;
case TYPE_TUPLE:
case TYPE_STRUCT:
case TYPE_EXPR:
@@ -349,7 +349,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);
@@ -374,7 +374,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
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;
}
@@ -1083,7 +1083,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
eval_unary_op_nums_only(-);
} break;
case UNARY_NOT:
- v->boolv = !val_truthiness(v, &e->unary.of->type);
+ v->boolv = !val_truthiness(*v, &e->unary.of->type);
break;
case UNARY_DEL:
if (of_type->kind == TYPE_PTR)
@@ -1191,7 +1191,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (i->cond) {
Value cond;
if (!eval_expr(ev, i->cond, &cond)) return false;
- if (val_truthiness(&cond, &i->cond->type)) {
+ if (val_truthiness(cond, &i->cond->type)) {
if (!eval_block(ev, &i->body, v)) return false;
} else if (i->next_elif) {
if (!eval_expr(ev, i->next_elif, v)) return false;
@@ -1207,7 +1207,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (w->cond) {
if (!eval_expr(ev, w->cond, &cond)) return false;
Type *cond_type = &w->cond->type;
- if (!val_truthiness(&cond, cond_type))
+ if (!val_truthiness(cond, cond_type))
break;
}
if (!eval_block(ev, &w->body, v)) return false;
diff --git a/main.c b/main.c
index 36c6b6d..e4e1a18 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
TODO:
-fix x ::= fn_that_returns_array(); fn_that_takes_array(x);
#if
variadic fns
#foreign variadic fns
diff --git a/parse.c b/parse.c
index 07af202..39a3863 100644
--- a/parse.c
+++ b/parse.c
@@ -1304,6 +1304,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
Token *start = t->token;
+ if (token_is_direct(t->token, DIRECT_IF)) {
+ goto if_expr;
+ }
if (t->token->kind == TOKEN_KW) switch (t->token->kw) {
case KW_FN: {
/* this is a function */
@@ -1327,8 +1330,13 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
return false;
goto success;
}
- case KW_IF: {
+ case KW_IF:
+ if_expr: {
IfExpr *i = e->if_ = parser_malloc(p, sizeof *i);
+ i->flags = 0;
+ if (t->token->kind == TOKEN_DIRECT) {
+ i->flags |= IF_STATIC;
+ }
e->kind = EXPR_IF;
++t->token;
Token *cond_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE);
@@ -1360,6 +1368,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
next->where.start = t->token;
curr->next_elif = next;
IfExpr *nexti = next->if_ = parser_malloc(p, sizeof *nexti);
+ nexti->flags = 0;
if (is_else) {
++t->token;
nexti->cond = NULL;
@@ -1853,6 +1862,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
Expression *single_arg = NULL; /* points to an expr if this is a directive with one expression argument */
switch (t->token->direct) {
+ case DIRECT_IF:
+ assert(0); /* handled above */
+ break;
case DIRECT_C:
e->kind = EXPR_C;
single_arg = e->c.code = parser_new_expr(p);
diff --git a/test.toc b/test.toc
index eee514a..987f3c7 100644
--- a/test.toc
+++ b/test.toc
@@ -1,70 +1,9 @@
-puti ::= fn(x: int) {
-//tcc's giving me "incompatible types for redefinition of 'printf'" for some reason (even though the declarations have the exact same type)
- #C("#ifndef __TINYC__
-extern int printf(const char *fmt, ...);
-#endif
-");
- #C("printf(\"%ld\\n\", (long)x);");
-};
-putf ::= fn(x: float) {
- #C("#ifndef __TINYC__
-extern int printf(const char *fmt, ...);
-#endif
-");
- #C("printf(\"%f\\n\", (double)x);");
-};
-
-// it would be nice if Arr.data.len == Arr.len (: but this will require some C code...
-Arr ::= fn (t :: Type) Type {
- struct {
- data : []t;
- len, cap : int;
- }
-};
-
-arr_add ::= fn(t :: Type, a : &Arr(t), x : t) {
- if a.len >= a.cap {
- a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
- for i := 0..a.len-1 {
- new_data[i] = a.data[i];
- }
- a.data = new_data;
- }
- a.data[a.len] = x;
- a.len += 1;
-};
-
-square ::= fn(t :: Type, x : t) t {
- a : Arr(t);
- for i := 1,2..2*x-1 {
- arr_add(t, &a, i);
- };
- sum := 0 as t;
- for i := 0..a.len-1 {
- sum += a.data[i];
- };
- sum
-};
-
-
-ArrInt ::= Arr(int);
-
-inc ::= fn(t :: Type, x : t) t {
- x + 1
-};
+#include "std/io.toc", io;
main ::= fn() {
- arr : ArrInt;
- farr : Arr(float);
- for i := 1..100 {
- arr_add(int, &arr, inc(int, square(int, i)));
- arr_add(float, &farr, inc(float, square(float, i as float)));
- }
- for i := 0..arr.len - 1 {
- puti(arr.data[i]);
- }
- for i := 0..farr.len - 1 {
- putf(farr.data[i]);
+ #if 3 > 5 {
+ io.puts("3 > 5");
+ } else {
+ io.puts("5 >= 3");
}
};
diff --git a/types.c b/types.c
index 55fca89..9095bc9 100644
--- a/types.c
+++ b/types.c
@@ -1624,6 +1624,41 @@ static Status types_expr(Typer *tr, Expression *e) {
case EXPR_IF: {
IfExpr *i = e->if_;
IfExpr *curr = i;
+ if (curr->flags & IF_STATIC) {
+ while (1) {
+ Expression *cond = curr->cond;
+ Expression *next = curr->next_elif;
+ Value v;
+ if (cond) {
+ if (!types_expr(tr, cond))
+ return false;
+ if (!types_block(tr, &curr->body))
+ return false;
+ if (!eval_expr(tr->evalr, cond, &v))
+ return false;
+ }
+ if (!cond || val_truthiness(v, &cond->type)) {
+ Block *true_block = typer_malloc(tr, sizeof *true_block);
+ *true_block = curr->body;
+ e->kind = EXPR_BLOCK;
+ e->block = true_block;
+ break;
+ }
+ if (!next) break;
+ curr = next->if_;
+ }
+ if (e->kind == EXPR_IF) {
+ /* all conds were false */
+ e->kind = EXPR_BLOCK;
+ e->block = typer_calloc(tr, 1, sizeof *e->block);
+ e->block->where = e->where;
+ idents_create(&e->block->idents, tr->allocr, e->block);
+ }
+ /* re-type */
+ if (!types_expr(tr, e))
+ return false;
+ return true;
+ }
Type *curr_type = t;
bool has_else = false;
if (!types_block(tr, &curr->body))
diff --git a/types.h b/types.h
index d8e780d..8d27695 100644
--- a/types.h
+++ b/types.h
@@ -242,11 +242,12 @@ typedef enum {
DIRECT_BUILTIN,
DIRECT_INCLUDE,
DIRECT_FORCE,
+ DIRECT_IF,
DIRECT_COUNT
} Directive;
static const char *directives[DIRECT_COUNT] =
- {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force"};
+ {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force", "if"};
typedef enum {
KW_SEMICOLON,
@@ -594,7 +595,12 @@ typedef struct CallExpr {
struct Instance *instance; /* NULL = ordinary function, no compile time args */
} CallExpr;
+enum {
+ IF_STATIC = 0x01
+};
+
typedef struct IfExpr {
+ U8 flags;
struct Expression *cond; /* NULL = this is an else */
struct Expression *next_elif; /* next elif/else of this statement */
Block body;