diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-15 17:26:52 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-15 17:26:52 -0500 |
commit | 054fec911b18dc0c8ec0180858b0bd00f60be90b (patch) | |
tree | 1d27f15bdc345044ea293e8c5ff3da6cda439861 | |
parent | e637aa3a416e0c90273f127a8d11b918356dfcc4 (diff) |
bug fixes for inference
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | infer.c | 29 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | test.toc | 63 | ||||
-rw-r--r-- | types.c | 16 |
5 files changed, 92 insertions, 26 deletions
@@ -1323,6 +1323,12 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { break; case EXPR_IDENT: { IdentDecl *idecl = ident_decl(e->ident); + if (!idecl) { + char *s = ident_to_str(e->ident); + err_print(e->where, "Undeclared identifier: %s.", s); + free(s); + return false; + } bool is_decl = idecl->kind == IDECL_DECL; Declaration *d = NULL; if (is_decl) { @@ -1,7 +1,8 @@ static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_where, Type *fn_type, Argument *args, Location where, U16 **param_indices); static bool types_expr(Typer *tr, Expression *e); -static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identifier *idents, Value *vals, Type *types) { +/* resolved_to should have the same value as to, but not consist of any identifiers which aren't in scope right now */ +static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expression *resolved_to, Identifier *idents, Value *vals, Type *types) { assert(!(match->flags & EXPR_FOUND_TYPE)); assert(to->flags & EXPR_FOUND_TYPE); switch (match->kind) { @@ -11,7 +12,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi if (*ident == match->ident) { long idx = ident - idents; types[idx] = to->type; - if (!eval_expr(tr->evalr, to, &vals[idx])) + if (!eval_expr(tr->evalr, resolved_to, &vals[idx])) return false; Copier c = copier_create(tr->allocr, tr->block); Value new_val; @@ -46,7 +47,8 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi } else { t_arg = &t_args[i]; } - if (!infer_from_expr(tr, &m_arg->val, t_arg, idents, vals, types)) + assert(t_arg->kind == EXPR_VAL); /* should have been evaluated */ + if (!infer_from_expr(tr, &m_arg->val, t_arg, t_arg, idents, vals, types)) return false; } } break; @@ -76,12 +78,13 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents } } break; case TYPE_FN: { + if (match->fn.constness || to->fn.constness) { + return true; + } if (to->kind != TYPE_FN) return true; if (arr_len(match->fn.types) != arr_len(to->fn.types)) return true; size_t i, len = arr_len(match->fn.types); for (i = 0; i < len; ++i) { - if (match->fn.constness[i] != to->fn.constness[i]) - return true; if (!infer_from_type(tr, &match->fn.types[i], &to->fn.types[i], idents, vals, types)) return false; } @@ -110,16 +113,16 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents case TYPE_EXPR: { Expression *to_expr = to->was_expr; Expression e = {0}; + e.kind = EXPR_TYPE; + e.typeval = *to; + e.flags = EXPR_FOUND_TYPE; + Type *type = &e.type; + type->flags = TYPE_IS_RESOLVED; + type->kind = TYPE_TYPE; if (!to_expr) { to_expr = &e; - to_expr->kind = EXPR_TYPE; - to_expr->typeval = *to; - to_expr->flags = EXPR_FOUND_TYPE; - Type *type = &to_expr->type; - type->flags = TYPE_IS_RESOLVED; - type->kind = TYPE_TYPE; } - if (!infer_from_expr(tr, match->expr, to_expr, idents, vals, types)) + if (!infer_from_expr(tr, match->expr, to_expr, &e, idents, vals, types)) return false; } break; case TYPE_ARR: { @@ -132,7 +135,7 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents n_type->kind = TYPE_BUILTIN; n_type->builtin = BUILTIN_I64; n_type->flags = TYPE_IS_RESOLVED; - if (!infer_from_expr(tr, match->arr.n_expr, &to_n_expr, idents, vals, types)) + if (!infer_from_expr(tr, match->arr.n_expr, &to_n_expr, &to_n_expr, idents, vals, types)) return false; if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types)) return false; @@ -20,6 +20,10 @@ /* TODO: inferred const params +make sure all parameters to a function which returns a type are constant +check that it still works when you specify the inferred param +--- +get ArrInt to work with inference packages X ::= newtype(int); or something don't allow while {3; 5} (once break is added) @@ -1,18 +1,63 @@ puti ::= fn(x: int) { - #C("printf(\"%ld\\n\", x)"); + #C("printf(\"%ld\\n\", (long)x); +"); }; putf ::= fn(x: float) { - #C("printf(\"%f\\n\", x)"); + #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 ::=, a : &Arr(t), x : t) { + if a.len >= a.cap { + a.cap = a.cap * 2 + 2; + new_data := new(t, a.cap); + each 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 ::=, x : t) t { + a : Arr(t); + each i := 1,2..2*x-1 { + arr_add(t, &a, i); + }; + sum := 0 as t; + each i := 0..a.len-1 { + sum += a.data[i]; + }; + sum }; -t ::= fn(a:: Type) Type {a}; -f ::= fn(b::=, u::=, a:t(b), x:t(u)) int{ -((3 as b) as u) as int +// ArrInt ::= Arr(int); + +inc ::= fn(t ::=, x : t) t { + x + 1 }; main ::= fn() { - x : t(int) = 3; - y : t(float) = 3.4; - puti(f(x,y)); -};
\ No newline at end of file + arr : Arr(int); + farr : Arr(float); + each i := 1..100 { + arr_add(&arr, inc(square(i))); + arr_add(&farr, inc(square(i as float))); + } + each i := 0..arr.len - 1 { + puti(arr.data[i]); + } + each i := 0..farr.len - 1 { + putf(farr.data[i]); + } +}; @@ -754,11 +754,19 @@ static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_wher return false; } param_idx = index; - } else if ((param->flags & (DECL_HAS_EXPR | DECL_INFER)) && param < last_param_without_default_value) { - /* this param must be named; so this is referring to a later parameter */ - --arg; } else { - param_idx = p; + if (param > (Declaration *)arr_last(fn->params)) { + err_print(arg->where, "Too many arguments to function!"); + info_print(fn_where, "Declaration is here."); + return false; + } + + if ((param->flags & (DECL_HAS_EXPR | DECL_INFER)) && param < last_param_without_default_value) { + /* this param must be named; so this is referring to a later parameter */ + --arg; + } else { + param_idx = p; + } } if (param_idx != -1) { |