diff options
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | parse.c | 28 | ||||
-rw-r--r-- | test.toc | 3 | ||||
-rw-r--r-- | types.c | 47 | ||||
-rw-r--r-- | util/err.c | 9 |
5 files changed, 63 insertions, 30 deletions
@@ -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: @@ -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: @@ -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); }; @@ -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 = ¶m_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; @@ -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 { |