summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c6
-rw-r--r--parse.c28
-rw-r--r--test.toc3
-rw-r--r--types.c47
-rw-r--r--util/err.c9
5 files changed, 63 insertions, 30 deletions
diff --git a/eval.c b/eval.c
index 9958718..c9ecfaa 100644
--- a/eval.c
+++ b/eval.c
@@ -14,17 +14,17 @@
static bool eval_expr_as_int(Expression *e, Integer *i) {
/* OPTIM: cache eval'd expression values? (probably only for declarations) */
switch (e->kind) {
- case EXPR_FLOAT_LITERAL:
+ case EXPR_LITERAL_FLOAT:
err_print(e->where, "Expected integer, but found floating-point literal.");
return false;
- case EXPR_INT_LITERAL:
+ case EXPR_LITERAL_INT:
if (e->intl > (UInteger)INTEGER_MAX) { /* TODO: FIXME */
err_print(e->where, "Overflow when evaluating integer.");
return false;
}
*i = (Integer)e->intl;
return true;
- case EXPR_STR_LITERAL:
+ case EXPR_LITERAL_STR:
err_print(e->where, "Expected integer, but found string literal.");
return false;
case EXPR_UNARY_OP:
diff --git a/parse.c b/parse.c
index f3e7efa..ec6afaa 100644
--- a/parse.c
+++ b/parse.c
@@ -51,9 +51,9 @@ typedef struct Block {
} Block;
typedef enum {
- EXPR_INT_LITERAL,
- EXPR_FLOAT_LITERAL,
- EXPR_STR_LITERAL,
+ EXPR_LITERAL_FLOAT,
+ EXPR_LITERAL_INT,
+ EXPR_LITERAL_STR,
EXPR_IDENT, /* variable or constant */
EXPR_BINARY_OP,
EXPR_UNARY_OP,
@@ -79,6 +79,12 @@ typedef struct {
Array args; /* of Expression */
} DirectExpr;
+typedef struct {
+ struct Expression *fn;
+ Array args; /* of Expression */
+ unsigned long out_var; /* which out variable is used for this call (used by cgen) */
+} CallExpr;
+
typedef struct Expression {
Location where;
ExprKind kind;
@@ -96,11 +102,7 @@ typedef struct Expression {
struct Expression *lhs;
struct Expression *rhs;
} binary;
- struct {
- struct Expression *fn;
- Array args; /* of Expression */
- unsigned long out_var; /* which out variable is used for this call (used by cgen) */
- } call;
+ CallExpr call;
DirectExpr direct;
Identifier ident;
struct FnExpr *fn;
@@ -620,9 +622,11 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
NumLiteral *num = &t->token->num;
switch (num->kind) {
case NUM_LITERAL_FLOAT:
+ e->kind = EXPR_LITERAL_FLOAT;
e->floatl = num->floatval;
break;
case NUM_LITERAL_INT:
+ e->kind = EXPR_LITERAL_INT;
e->intl = num->intval;
break;
}
@@ -632,7 +636,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
e->ident = t->token->ident;
break;
case TOKEN_STR_LITERAL:
- e->kind = EXPR_STR_LITERAL;
+ e->kind = EXPR_LITERAL_STR;
e->strl = t->token->str;
break;
default:
@@ -1217,13 +1221,13 @@ static void fprint_args(FILE *out, Array *args) {
static void fprint_expr(FILE *out, Expression *e) {
PARSE_PRINT_LOCATION(e->where);
switch (e->kind) {
- case EXPR_INT_LITERAL:
+ case EXPR_LITERAL_INT:
fprintf(out, "%lld", (long long)e->intl);
break;
- case EXPR_FLOAT_LITERAL:
+ case EXPR_LITERAL_FLOAT:
fprintf(out, "%f", (double)e->floatl);
break;
- case EXPR_STR_LITERAL:
+ case EXPR_LITERAL_STR:
fprintf(out, "\"%s\"", e->strl.str);
break;
case EXPR_IDENT:
diff --git a/test.toc b/test.toc
index d8a82af..01ee66d 100644
--- a/test.toc
+++ b/test.toc
@@ -8,5 +8,6 @@ times2 @= fn(x: int) int { x + x };
main @= fn() {
print_int(times2(5));
- foo := fn (x, y, z : f32, A:f64) {};
+ foo := fn (x, y, z,w : f32, A:f64) {};
+ foo(foo,4,5,3,5);
};
diff --git a/types.c b/types.c
index 8ce7b4d..c243d6a 100644
--- a/types.c
+++ b/types.c
@@ -223,8 +223,9 @@ static bool type_resolve(Type *t) {
return true;
}
-/* NOTE: this does descend into un/binary ops, etc. but NOT into functions */
+/* 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) */
t->flags = 0;
t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */
switch (e->kind) {
@@ -244,15 +245,15 @@ static bool type_of_expr(Expression *e, Type *t) {
*param_type = param_types[i];
}
} break;
- case EXPR_INT_LITERAL:
+ case EXPR_LITERAL_INT:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_I64;
t->flags |= TYPE_FLAG_FLEXIBLE;
break;
- case EXPR_STR_LITERAL:
+ case EXPR_LITERAL_STR:
t->kind = TYPE_UNKNOWN; /* TODO */
break;
- case EXPR_FLOAT_LITERAL:
+ case EXPR_LITERAL_FLOAT:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_F32;
t->flags |= TYPE_FLAG_FLEXIBLE;
@@ -261,20 +262,44 @@ static bool type_of_expr(Expression *e, Type *t) {
if (!type_of_ident(e->where, e->ident, t, false)) return false;
} break;
case EXPR_CALL: {
- Expression *f = e->call.fn;
+ CallExpr *c = &e->call;
+ Expression *f = c->fn;
if (f->kind == EXPR_IDENT) {
/* 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;
}
+ arr_foreach(&c->args, Expression, arg) {
+ if (!type_of_expr(arg, &arg->type))
+ return false;
+ }
if (f->type.kind != TYPE_FN) {
char *type = type_to_str(&f->type);
err_print(e->where, "Calling non-function (type %s).", type);
return false;
}
- /* TODO: Make sure args match fn type */
- *t = *(Type*)f->type.fn.types.data;
+ Type *ret_type = (Type *)f->type.fn.types.data;
+ Type *param_types = ret_type + 1;
+ Expression *args = c->args.data;
+ size_t nparams = f->type.fn.types.len - 1;
+ if (nparams != c->args.len) {
+ err_print(e->where, "Expected %lu arguments to function, but got %lu.", (unsigned long)nparams, (unsigned long)c->args.len);
+ return false;
+ }
+ bool ret = true;
+ for (size_t p = 0; p < nparams; p++) {
+ Type *expected = &param_types[p];
+ Type *got = &args[p].type;
+ if (!type_eq(expected, got)) {
+ ret = false;
+ char *estr = type_to_str(expected);
+ char *gstr = type_to_str(got);
+ err_print(args[p].where, "Expected type %s as %lu%s argument to function, but got %s.", estr, 1+(unsigned long)p, ordinals(1+p), gstr);
+ }
+ }
+ if (!ret) return false;
+ *t = *ret_type;
break;
}
case EXPR_DIRECT:
@@ -407,6 +432,7 @@ static bool types_block(Block *b) {
return ret;
}
+/* 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;
@@ -438,13 +464,6 @@ static bool types_expr(Expression *e) {
return false;
}
} break;
- case EXPR_CALL: {
- bool ret = true;
- arr_foreach(&e->call.args, Expression, arg) {
- if (!types_expr(arg)) ret = false;
- }
- return ret;
- } break;
default: break;
}
return true;
diff --git a/util/err.c b/util/err.c
index 3fe3b53..c5d32b2 100644
--- a/util/err.c
+++ b/util/err.c
@@ -12,6 +12,15 @@
#define TEXT_IMPORTANT(x) x
#endif
+static inline const char *ordinals(size_t x) {
+ switch (x % 10) {
+ case 1: return "st";
+ case 2: return "nd";
+ case 3: return "rd";
+ default: return "th";
+ }
+}
+
typedef uint32_t LineNo;
typedef struct {