diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-14 11:20:32 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-14 11:20:32 -0500 |
commit | e69a6cb8ff340baae6e4adee5414238751beaa1f (patch) | |
tree | 8f88ef0f917f40452f994656e7786d1a1622024e | |
parent | cf76d56b37a368fda3d70a548192239a3ce45bbb (diff) |
basic inferred params
-rw-r--r-- | allocator.c | 2 | ||||
-rw-r--r-- | copy.c | 43 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | infer.c | 88 | ||||
-rw-r--r-- | parse.c | 5 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | types.c | 36 |
7 files changed, 113 insertions, 65 deletions
diff --git a/allocator.c b/allocator.c index c961185..6721e94 100644 --- a/allocator.c +++ b/allocator.c @@ -7,7 +7,9 @@ static void *err_malloc(size_t bytes); static void *err_calloc(size_t n, size_t sz); static void *err_realloc(void *prev, size_t new_size); +#ifdef TOC_DEBUG #define NO_ALLOCATOR 1 /* useful for debugging; valgrind (maybe) checks writing past the end of a malloc, but that won't work with an allocator */ +#endif /* number of bytes a page hold, not including the header */ #define PAGE_BYTES (16384 - sizeof(Page)) #define PAGE_MAX_ALIGNS (PAGE_BYTES / sizeof(MaxAlign)) @@ -2,8 +2,15 @@ Copyright (C) 2019 Leo Tenenbaum. This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever. You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. + + + these copy functions MUST be used before typing!!!! (except for copy_val) + + ----- + IMPORTANT: + These functions are like memcpy, in that in and out must not overlap! + ----- */ -/* these copy functions MUST be used before typing!!!! (except for copy_val) */ typedef struct { Allocator *allocr; @@ -49,15 +56,6 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { memcpy(out->struc, in->struc, bytes); } break; case TYPE_TYPE: - /* copy_type(c, out->type = allocr_malloc(c->allocr, sizeof *out->type), in->type); */ - /* - i don't think this can be a problem right now, - but might eventually be, - if a function returns a type and - the old type doesn't work when the stuff on the stack - is freed. if you switch back to using a copier, make sure you check where - copy_val(NULL, ...) is used!!! - */ *out = *in; break; case TYPE_EXPR: @@ -65,9 +63,18 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { } } -/* only works on unresolved types */ +static void copy_val_full(Copier *c, Value *out, Value *in, Type *t) { + if (t->kind == TYPE_TYPE) { + Type *new_type = allocr_malloc(c->allocr, sizeof *new_type); + copy_type(c, new_type, in->type); + out->type = new_type; + } else { + copy_val(c->allocr, out, in, t); + } +} + +/* only works on unresolved and resolved types */ static void copy_type(Copier *c, Type *out, Type *in) { - assert(!(in->flags & TYPE_IS_RESOLVED)); *out = *in; switch (in->kind) { case TYPE_BUILTIN: @@ -95,12 +102,12 @@ static void copy_type(Copier *c, Type *out, Type *in) { } } break; case TYPE_ARR: - /* if (in->flags & TYPE_IS_RESOLVED) { */ - /* out->arr.n = in->arr.n; */ - /* } else { */ - out->arr.n_expr = allocr_malloc(c->allocr, sizeof *out->arr.n_expr); - copy_expr(c, out->arr.n_expr, in->arr.n_expr); - /* } */ + if (in->flags & TYPE_IS_RESOLVED) { + out->arr.n = in->arr.n; + } else { + out->arr.n_expr = allocr_malloc(c->allocr, sizeof *out->arr.n_expr); + copy_expr(c, out->arr.n_expr, in->arr.n_expr); + } out->arr.of = allocr_malloc(c->allocr, sizeof *out->arr.of); copy_type(c, out->arr.of, in->arr.of); break; @@ -1331,7 +1331,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { *v = idecl->val; } else if (is_decl && (d->flags & DECL_IS_CONST)) { if (!(d->flags & DECL_FOUND_VAL)) { - assert(d->flags & DECL_HAS_EXPR); /* KEEP */ + assert(d->flags & DECL_HAS_EXPR); if (!eval_expr(ev, &d->expr, &d->val)) return false; d->flags |= DECL_FOUND_VAL; } @@ -1,77 +1,107 @@ -static bool infer_from_expr(Expression *match, Expression *to, Identifier *idents, Value *vals, Type *types) { +static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identifier *idents, Value *vals, Type *types) { + assert(to->flags & EXPR_FOUND_TYPE); + switch (match->kind) { + case EXPR_IDENT: + /* an identifier! maybe it's one of idents... */ + arr_foreach(idents, Identifier, ident) { + if (*ident == match->ident) { + long idx = ident - idents; + types[idx] = to->type; + if (!eval_expr(tr->evalr, to, &vals[idx])) + return false; + Copier c = copier_create(tr->allocr, tr->block); + Value new_val; + copy_val_full(&c, &new_val, &vals[idx], &to->type); + vals[idx] = new_val; + break; + } + } + break; + default: break; + } return true; } /* if match is not the same kind of type as to, returns true */ -static bool infer_from_type(Type *match, Type *to, Identifier *idents, Value *vals, Type *types) { +static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents, Value *vals, Type *types) { assert(to->flags & TYPE_IS_RESOLVED); - switch (to->kind) { + switch (match->kind) { case TYPE_VOID: case TYPE_UNKNOWN: case TYPE_BUILTIN: case TYPE_TYPE: break; /* nothing we can do here */ case TYPE_TUPLE: { - if (match->kind != TYPE_TUPLE) return true; + if (to->kind != TYPE_TUPLE) return true; if (arr_len(match->tuple) != arr_len(to->tuple)) return true; Type *b = to->tuple; arr_foreach(match->tuple, Type, a) { - if (!infer_from_type(a, b, idents, vals, types)) + if (!infer_from_type(tr, a, b, idents, vals, types)) return false; ++b; } } break; case TYPE_FN: { - if (match->kind != TYPE_FN) 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(&match->fn.types[i], &to->fn.types[i], idents, vals, types)) + if (!infer_from_type(tr, &match->fn.types[i], &to->fn.types[i], idents, vals, types)) return false; } } break; case TYPE_PTR: - if (match->kind != TYPE_PTR) return true; - if (!infer_from_type(match->ptr, to->ptr, idents, vals, types)) + if (to->kind != TYPE_PTR) return true; + if (!infer_from_type(tr, match->ptr, to->ptr, idents, vals, types)) return false; break; case TYPE_SLICE: - if (match->kind != TYPE_SLICE) return true; - if (!infer_from_type(match->slice, to->slice, idents, vals, types)) + if (to->kind != TYPE_SLICE) return true; + if (!infer_from_type(tr, match->slice, to->slice, idents, vals, types)) return false; break; case TYPE_STRUCT: { - if (match->kind != TYPE_STRUCT) return true; + if (to->kind != TYPE_STRUCT) return true; Field *fields_m = match->struc->fields; Field *fields_t = to->struc->fields; size_t i, len = arr_len(fields_m); if (len != arr_len(fields_t)) return true; for (i = 0; i < len; ++i) { - if (!infer_from_type(fields_m[i].type, fields_t[i].type, idents, vals, types)) + if (!infer_from_type(tr, fields_m[i].type, fields_t[i].type, idents, vals, types)) return false; } } break; - case TYPE_EXPR: - if (to->was_expr) - if (!infer_from_expr(match->expr, to->was_expr, idents, vals, types)) - return false; - break; + case TYPE_EXPR: { + Expression *to_expr = to->was_expr; + Expression e = {0}; + 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)) + return false; + } break; case TYPE_ARR: { - if (match->kind != TYPE_ARR) return true; - Expression match_n_expr = {0}; - match_n_expr.kind = EXPR_LITERAL_INT; - match_n_expr.intl = match->arr.n; - match_n_expr.flags = EXPR_FOUND_TYPE; - Type *n_type = &match_n_expr.type; + if (to->kind != TYPE_ARR) return true; + Expression to_n_expr = {0}; + to_n_expr.kind = EXPR_LITERAL_INT; + to_n_expr.intl = to->arr.n; + to_n_expr.flags = EXPR_FOUND_TYPE; + Type *n_type = &to_n_expr.type; n_type->kind = TYPE_BUILTIN; n_type->builtin = BUILTIN_I64; n_type->flags = TYPE_IS_RESOLVED; - if (!infer_from_expr(&match_n_expr, to->arr.n_expr, idents, vals, types)) + if (!infer_from_expr(tr, match->arr.n_expr, &to_n_expr, idents, vals, types)) return false; - if (!infer_from_type(match->arr.of, to->slice, idents, vals, types)) + if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types)) return false; } break; } @@ -80,11 +110,11 @@ static bool infer_from_type(Type *match, Type *to, Identifier *idents, Value *va /* match and to are dynamic arrays of equal size -idents is a dyn array +idents is a dyn array of distinct identifiers find the value of each ident by matching match[i] to to[i], i = 0..arr_len(match)-1 all the types in match must be resolved, and all the types in to must be unresolved */ -static bool infer_ident_vals(Type **match, Type **to, Identifier *idents, Value *vals, Type *types) { +static bool infer_ident_vals(Typer *tr, Type **match, Type **to, Identifier *idents, Value *vals, Type *types) { size_t ntypes = arr_len(match); size_t i; size_t nidents = arr_len(idents); @@ -97,7 +127,7 @@ static bool infer_ident_vals(Type **match, Type **to, Identifier *idents, Value } for (i = 0; i < ntypes; ++i) { - if (!infer_from_type(*match, *to, idents, vals, types)) + if (!infer_from_type(tr, *match, *to, idents, vals, types)) return false; ++match, ++to; } @@ -1966,6 +1966,11 @@ static void fprint_type(FILE *out, Type *t) { free(s); } +static void print_type(Type *t) { + fprint_type(stdout, t); + printf("\n"); +} + static void fprint_block(FILE *out, Block *b) { fprintf(out, "{\n"); @@ -2,6 +2,8 @@ f ::= fn(t::=, x :t) t { x + 1 }; +// test: fn(t::=int,u::=t,x:u)u + main ::= fn() { f(13); };
\ No newline at end of file @@ -200,7 +200,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) bool entered_fn = false; size_t param_idx; FnExpr *prev_fn = tr->fn; - FnExpr fn_copy; + FnExpr fn_copy = {0}; Block *prev_block = tr->block; /* @@ -1279,9 +1279,9 @@ static bool types_expr(Typer *tr, Expression *e) { } size_t ninferred_idents = arr_len(inferred_idents); - Value *inferred_vals = typer_malloc(tr, ninferred_idents * sizeof *inferred_vals); - Type *inferred_types = typer_malloc(tr, ninferred_idents * sizeof *inferred_types); - if (!infer_ident_vals(decl_types, arg_types, inferred_idents, inferred_vals, inferred_types)) + Value *inferred_vals = malloc(ninferred_idents * sizeof *inferred_vals); + Type *inferred_types = malloc(ninferred_idents * sizeof *inferred_types); + if (!infer_ident_vals(tr, decl_types, arg_types, inferred_idents, inferred_vals, inferred_types)) return false; { Type *type = inferred_types; @@ -1304,17 +1304,13 @@ static bool types_expr(Typer *tr, Expression *e) { i = 0; arr_foreach(fn->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if (param->flags & DECL_INFER) { - param->expr.kind = EXPR_VAL; - param->expr.flags = 0; - param->expr.val = inferred_vals[i]; - param->expr.type = inferred_types[i]; - param->expr.flags |= EXPR_FOUND_TYPE; - param->type = param->expr.type; - param->flags |= DECL_HAS_EXPR|DECL_FOUND_TYPE; - ++i; - } + if (param->flags & DECL_INFER) { + Value *val = &inferred_vals[i]; + Type *type = &inferred_types[i]; + param->val = *val; + param->type = *type; + param->flags |= DECL_FOUND_VAL | DECL_FOUND_TYPE; + ++i; } } /* type return declarations, etc */ @@ -1322,11 +1318,18 @@ static bool types_expr(Typer *tr, Expression *e) { return false; /* deal with default arguments */ - i = 0; arr_foreach(fn->params, Declaration, param) { arr_foreach(param->idents, Identifier, ident) { if (!params_set[i]) { + if (param->flags & DECL_INFER) { + arg_exprs[i].kind = EXPR_VAL; + arg_exprs[i].flags = EXPR_FOUND_TYPE; + arg_exprs[i].type = table_index_type.tuple[i+1] = param_types[i] = param->type; + arg_exprs[i].val = table_index.tuple[i+1] = param->val; + params_set[i] = true; + continue; + } assert(param->flags & DECL_HAS_EXPR); assert(param->expr.kind == EXPR_VAL); /* this was done by type_of_fn */ arg_exprs[i] = param->expr; @@ -1349,7 +1352,6 @@ static bool types_expr(Typer *tr, Expression *e) { /* check types of arguments */ for (size_t p = 0; p < nparams; ++p) { Expression *arg = &arg_exprs[p]; - Type *expected = ¶m_types[p]; Type *got = &arg->type; if (!type_eq(expected, got)) { |