summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c4
-rw-r--r--test.toc2
-rw-r--r--types.c38
3 files changed, 30 insertions, 14 deletions
diff --git a/parse.c b/parse.c
index ec6afaa..f3415cf 100644
--- a/parse.c
+++ b/parse.c
@@ -85,9 +85,12 @@ typedef struct {
unsigned long out_var; /* which out variable is used for this call (used by cgen) */
} CallExpr;
+#define EXPR_FLAG_FOUND_TYPE 0x01
+
typedef struct Expression {
Location where;
ExprKind kind;
+ uint16_t flags;
Type type;
union {
Floating floatl;
@@ -609,6 +612,7 @@ static bool parse_args(Parser *p, Array *args) {
static bool parse_expr(Parser *p, Expression *e, Token *end) {
Tokenizer *t = p->tokr;
+ e->flags = 0;
if (end == NULL) return false;
e->where = t->token->where;
if (end <= t->token) {
diff --git a/test.toc b/test.toc
index 01ee66d..115f97b 100644
--- a/test.toc
+++ b/test.toc
@@ -9,5 +9,5 @@ times2 @= fn(x: int) int { x + x };
main @= fn() {
print_int(times2(5));
foo := fn (x, y, z,w : f32, A:f64) {};
- foo(foo,4,5,3,5);
+ foo(3,4,5,3,5);
};
diff --git a/types.c b/types.c
index c243d6a..c17aff6 100644
--- a/types.c
+++ b/types.c
@@ -1,3 +1,4 @@
+static bool type_of_expr(Expression *e);
static bool types_stmt(Statement *s);
static bool types_expr(Expression *e);
@@ -144,7 +145,6 @@ static bool expr_must_lval(Expression *e) {
return false;
}
-static bool type_of_expr(Expression *e, Type *t);
static bool type_of_ident(Location where, Identifier i, Type *t, bool allow_use_before_decl) {
IdentDecl *decl = ident_decl(i);
if (!decl) {
@@ -170,8 +170,9 @@ static bool type_of_ident(Location where, Identifier i, Type *t, bool allow_use_
if (d->flags & DECL_FLAG_ANNOTATES_TYPE) {
decl_type = d->type;
} else {
- if (!type_of_expr(&d->expr, &decl_type))
+ if (!type_of_expr(&d->expr))
return false;
+ decl_type = d->expr.type;
}
if (d->idents.len > 1) {
@@ -224,8 +225,9 @@ static bool type_resolve(Type *t) {
}
/* NOTE: this does descend into un/binary ops, calls, etc. but NOT into any blocks */
-static bool type_of_expr(Expression *e, Type *t) {
- /* TODO: only get the type of an expr once (flag) */
+static bool type_of_expr(Expression *e) {
+ if (e->flags & EXPR_FLAG_FOUND_TYPE) return true;
+ Type *t = &e->type;
t->flags = 0;
t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */
switch (e->kind) {
@@ -268,10 +270,10 @@ static bool type_of_expr(Expression *e, Type *t) {
/* allow calling a function before declaring it */
if (!type_of_ident(f->where, f->ident, &f->type, true)) return false;
} else {
- if (!type_of_expr(f, &f->type)) return false;
+ if (!type_of_expr(f)) return false;
}
arr_foreach(&c->args, Expression, arg) {
- if (!type_of_expr(arg, &arg->type))
+ if (!type_of_expr(arg))
return false;
}
if (f->type.kind != TYPE_FN) {
@@ -304,14 +306,24 @@ static bool type_of_expr(Expression *e, Type *t) {
}
case EXPR_DIRECT:
t->kind = TYPE_UNKNOWN;
- /* TODO: make sure direct args have the right type */
- arr_foreach(&e->direct.args, Expression, arg) {
+ arr_foreach(&e->direct.args, Expression, arg) {
types_expr(arg);
}
+ switch (e->direct.which) {
+ case DIRECT_C: {
+ size_t n_args = e->direct.args.len;
+ if (n_args != 1) {
+ err_print(e->where, "#C call should have one string argument (got %lu arguments).", (unsigned long)n_args);
+ return false;
+ }
+ /* TODO: when string types are added, check */
+ } break;
+ case DIRECT_COUNT: assert(0); return false;
+ }
break;
case EXPR_UNARY_OP: {
Type *of_type = &e->unary.of->type;
- if (!type_of_expr(e->unary.of, of_type)) return false;
+ if (!type_of_expr(e->unary.of)) return false;
switch (e->unary.op) {
case UNARY_MINUS:
if (of_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(of_type->builtin)) {
@@ -326,8 +338,8 @@ static bool type_of_expr(Expression *e, Type *t) {
case EXPR_BINARY_OP: {
Type *lhs_type = &e->binary.lhs->type;
Type *rhs_type = &e->binary.rhs->type;
- if (!type_of_expr(e->binary.lhs, lhs_type)
- || !type_of_expr(e->binary.rhs, rhs_type))
+ if (!type_of_expr(e->binary.lhs)
+ || !type_of_expr(e->binary.rhs))
return false;
switch (e->binary.op) {
case BINARY_SET:
@@ -416,6 +428,7 @@ static bool type_of_expr(Expression *e, Type *t) {
}
} break;
}
+ e->flags |= EXPR_FLAG_FOUND_TYPE;
return true;
}
@@ -434,8 +447,7 @@ static bool types_block(Block *b) {
/* does descend into blocks, unlike type_of_expr. */
static bool types_expr(Expression *e) {
- Type *t = &e->type;
- if (!type_of_expr(e, t)) return false;
+ if (!type_of_expr(e)) return false;
switch (e->kind) {
case EXPR_FN: {
assert(e->type.kind == TYPE_FN);