summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-14 11:20:32 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-14 11:20:32 -0500
commite69a6cb8ff340baae6e4adee5414238751beaa1f (patch)
tree8f88ef0f917f40452f994656e7786d1a1622024e
parentcf76d56b37a368fda3d70a548192239a3ce45bbb (diff)
basic inferred params
-rw-r--r--allocator.c2
-rw-r--r--copy.c43
-rw-r--r--eval.c2
-rw-r--r--infer.c88
-rw-r--r--parse.c5
-rw-r--r--test.toc2
-rw-r--r--types.c36
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))
diff --git a/copy.c b/copy.c
index e6e9e9f..98be855 100644
--- a/copy.c
+++ b/copy.c
@@ -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;
diff --git a/eval.c b/eval.c
index 65ada12..c35ca48 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
}
diff --git a/infer.c b/infer.c
index b555353..6d35d06 100644
--- a/infer.c
+++ b/infer.c
@@ -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;
}
diff --git a/parse.c b/parse.c
index f64ffed..7599a97 100644
--- a/parse.c
+++ b/parse.c
@@ -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");
diff --git a/test.toc b/test.toc
index 74980c0..24b24b4 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/types.c b/types.c
index 9442cb6..5e9fb6e 100644
--- a/types.c
+++ b/types.c
@@ -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 = &param_types[p];
Type *got = &arg->type;
if (!type_eq(expected, got)) {