From 44f477931801e5d30db344d740ad2bededadc01c Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 23 Apr 2020 15:00:37 -0400 Subject: got rid of call inference; now inference is much simpler --- cgen.c | 1 + eval.c | 2 +- infer.c | 136 +++++++++++---------------------------------------------------- main.c | 1 - parse.c | 15 ++++--- test.toc | 11 +++++- types.c | 26 ++---------- types.h | 2 - 8 files changed, 47 insertions(+), 147 deletions(-) diff --git a/cgen.c b/cgen.c index 08631f5..b2d64f2 100644 --- a/cgen.c +++ b/cgen.c @@ -263,6 +263,7 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) { } static bool fn_has_instances(FnExpr *f) { + if (f->flags & FN_EXPR_FOREIGN) return false; if (fn_has_any_const_params(f)) return true; if (!arr_len(f->params)) return false; return type_is_builtin(&arr_last(f->params).type, BUILTIN_VARARGS); diff --git a/eval.c b/eval.c index cb74e0f..8b0c552 100644 --- a/eval.c +++ b/eval.c @@ -1065,7 +1065,7 @@ static void decl_remove_val(Declaration *d) { } static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { - + assert(e->flags & EXPR_FOUND_TYPE); #define eval_unary_op_one(low, up, op) \ case BUILTIN_##up: \ v->low = (up)(op of.low); break diff --git a/infer.c b/infer.c index fceeaa4..e131583 100644 --- a/infer.c +++ b/infer.c @@ -2,7 +2,7 @@ static bool call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Loca static bool parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where); 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) { +static bool infer_from_expr(Typer *tr, Expression *match, Value to, Type *to_type, Location to_where, Identifier *idents, Value *vals, Type *types) { #if 0 printf("Matching "); fprint_expr(stdout, match); @@ -12,20 +12,15 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi #endif assert(!(match->flags & EXPR_FOUND_TYPE)); - assert(to->flags & EXPR_FOUND_TYPE); + assert(to_type->flags & TYPE_IS_RESOLVED); 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; + types[idx] = *to_type; + vals[idx] = to; break; } } @@ -35,20 +30,18 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi return false; if (type_is_builtin(&match->call.fn->type, BUILTIN_TYPE)) { /* it's a parameterized struct */ - Value fn_val; - if (!eval_expr(tr->evalr, to, &fn_val)) - return false; - if (!type_is_builtin(&to->type, BUILTIN_TYPE) || fn_val.type->kind != TYPE_STRUCT) { - err_print(to->where, "Wrong argument type. Expected this to be a struct, but it's not."); + if (!type_is_builtin(to_type, BUILTIN_TYPE) || to.type->kind != TYPE_STRUCT) { + err_print(to_where, "Wrong argument type. Expected this to be a struct, but it's not."); info_print(match->where, "Parameter was declared here."); return false; } + Type *fn_type = to.type; I16 *order; - if (!parameterized_struct_arg_order(fn_val.type->struc, match->call.args, &order, match->where)) { + if (!parameterized_struct_arg_order(fn_type->struc, match->call.args, &order, match->where)) { free(order); return false; } - Declaration *params = to->typeval->struc->params; + Declaration *params = fn_type->struc->params; int arg_idx = 0; arr_foreach(params, Declaration, param) { int ident_idx = 0; @@ -56,12 +49,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi if (order[arg_idx] != -1) { Expression *arg = &match->call.args[order[arg_idx]].val; Value val = *decl_val_at_index(param, ident_idx); - Expression val_expr = {0}; - val_expr.kind = EXPR_VAL; - val_expr.val = val; - val_expr.type = *decl_type_at_index(param, ident_idx); - val_expr.flags = EXPR_FOUND_TYPE; - if (!infer_from_expr(tr, arg, &val_expr, idents, vals, types)) { + if (!infer_from_expr(tr, arg, val, decl_type_at_index(param, ident_idx), param->where, idents, vals, types)) { free(order); return false; } @@ -72,74 +60,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi } free(order); } - - while (to->kind == EXPR_IDENT) { - Identifier i = to->ident; - Declaration *decl = i->decl; - int index = ident_index_in_decl(i, decl); - Expression *expr = NULL; - if (decl->type.kind == TYPE_TUPLE) { - if (decl->expr.kind == EXPR_TUPLE) { - expr = &decl->expr.tuple[index]; - } - } else { - expr = &decl->expr; - } - if (expr) to = expr; - } - if (to->kind != EXPR_CALL) { - if (to->kind == EXPR_TYPE) { - to = to->typeval->was_expr; - } - if (!to || to->kind != EXPR_CALL) { - return true; - } - } - - Argument *m_args = match->call.args; - size_t nargs = arr_len(m_args); - Expression *t_args = to->call.arg_exprs; - I16 *order = NULL; - Expression *f = match->call.fn; - Identifier ident = f->ident; - bool is_direct_fn = f->kind == EXPR_IDENT && (ident->decl->flags & DECL_HAS_EXPR) && ident->decl->expr.kind == EXPR_FN; - if (!types_expr(tr, f)) - return false; - if (f->type.kind != TYPE_FN) { - char *s = type_to_str(&f->type); - err_print(f->where, "Calling non-function type %s.", s); - return false; - } - if (is_direct_fn) { - FnExpr *fn_decl = ident->decl->expr.fn; - if (!call_arg_param_order(fn_decl, &f->type, m_args, match->where, &order)) { - free(order); - return false; - } - } - size_t nparams = arr_len(f->type.fn.types) - 1; - if (!order && nparams != nargs) { - /* wrong number of parameters? let typing deal with it... */ - free(order); - return true; - } - for (size_t i = 0; i < nparams; ++i) { - if (!order || order[i] != -1) { - Argument *m_arg = &m_args[order ? (size_t)order[i] : i]; - Expression *t_arg; - if (is_direct_fn) { - t_arg = &t_args[i]; - } else { - t_arg = &t_args[i]; - } - if (t_arg->kind == EXPR_VAL) { - /* was evaluated, because it's const */ - if (!infer_from_expr(tr, &m_arg->val, t_arg, idents, vals, types)) - return false; - } - } - } - free(order); + /* don't try to match other kinds of function calls. it's impossible to get any information out of it. */ } break; default: break; } @@ -200,34 +121,21 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents no sane person will ever write something that needs this */ break; case TYPE_EXPR: { - Expression *to_expr = to->was_expr; - Expression e = {0}; - e.kind = EXPR_TYPE; - e.typeval = allocr_malloc(tr->allocr, sizeof *e.typeval); - *e.typeval = *to; - e.flags = EXPR_FOUND_TYPE; - e.where = where; - Type *type = &e.type; - type->flags = TYPE_IS_RESOLVED; - type->kind = TYPE_BUILTIN; - type->builtin = BUILTIN_TYPE; - if (!to_expr) { - to_expr = &e; - } - if (!infer_from_expr(tr, match->expr, to_expr, idents, vals, types)) + Type type; + construct_resolved_builtin_type(&type, BUILTIN_TYPE); + Value val = {0}; + val.type = to; + if (!infer_from_expr(tr, match->expr, val, &type, where, idents, vals, types)) return false; } break; case TYPE_ARR: { 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(tr, match->arr.n_expr, &to_n_expr, idents, vals, types)) + Type n_type; + construct_resolved_builtin_type(&n_type, BUILTIN_I64); + Value val; + val.i64 = (I64)to->arr.n; + /* try to match match's n expr to to's value */ + if (!infer_from_expr(tr, match->arr.n_expr, val, &n_type, where, idents, vals, types)) return false; if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types, where)) return false; diff --git a/main.c b/main.c index b3508da..1529b68 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,6 @@ /* @TODO: -consider: don't do inference for function calls; get rid of was_expr -- now that we have struct params EXPR_IDENT should be a string before typing, also struct member accesses do we need the possibility that IdentSlot.decl is NULL? use diff --git a/parse.c b/parse.c index 9a4d57f..0de36f8 100644 --- a/parse.c +++ b/parse.c @@ -27,6 +27,8 @@ static bool is_decl(Tokenizer *t); static inline bool ends_decl(Token *t, U16 flags); static bool fn_has_any_const_params(FnExpr *f) { + if (f->flags & FN_EXPR_FOREIGN) + return false; arr_foreach(f->params, Declaration, param) if (param->flags & (DECL_IS_CONST | DECL_SEMI_CONST)) return true; @@ -633,7 +635,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) { p->block = prev_block; if (!parse_block(p, &struc->body, PARSE_BLOCK_DONT_CREATE_IDENTS)) return false; - struc->where = struc->body.where; + parser_put_end(p, &struc->where); break; struct_fail: @@ -1211,6 +1213,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } { Token *before = t->token; + /* @OPTIM very few expressions are types */ if (parser_is_definitely_type(p, NULL)) { /* it's a type! */ e->kind = EXPR_TYPE; @@ -1536,13 +1539,11 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { ret_ctype->kind = CTYPE_NONE; ret_type->kind = TYPE_VOID; ret_type->flags = 0; - ret_type->was_expr = NULL; } else { if (!parse_c_type(p, ret_ctype, ret_type)) return false; } - parser_put_end(p, &fn->where); - return true; + goto success; } /* NOTE: the . operator is not handled here, but further down, in order to allow some_struct.fn_member() */ @@ -2173,7 +2174,6 @@ static Status parse_decl(Parser *p, Declaration *d, U16 flags) { if (token_is_kw(t->token, KW_DOTDOT)) { d->type.kind = TYPE_BUILTIN; d->type.flags = 0; - d->type.was_expr = NULL; d->type.builtin = BUILTIN_VARARGS; is_varargs = true; if (d->flags & DECL_SEMI_CONST) { @@ -2987,3 +2987,8 @@ static bool expr_is_definitely_const(Expression *e) { return false; } +static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) { + t->kind = TYPE_BUILTIN; + t->builtin = builtin; + t->flags = TYPE_IS_RESOLVED; +} diff --git a/test.toc b/test.toc index 843b3ad..e2e5a57 100644 --- a/test.toc +++ b/test.toc @@ -1,4 +1,11 @@ -#include "io.toc", io; +Point ::= struct { + a ::= 3; +} -#include "mem.toc", mem; + +main ::= fn() { + use p: Point; + a; + +} diff --git a/types.c b/types.c index d8998d2..183f350 100644 --- a/types.c +++ b/types.c @@ -32,13 +32,6 @@ static inline void typer_block_exit(Typer *tr) { tr->block = arr_last(tr->blocks); } -static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) { - t->kind = TYPE_BUILTIN; - t->builtin = builtin; - t->was_expr = NULL; - t->flags = TYPE_IS_RESOLVED; -} - static size_t compiler_sizeof_builtin(BuiltinType b) { switch (b) { case BUILTIN_I8: return sizeof(I8); @@ -558,7 +551,6 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } else { f->ret_type.kind = TYPE_TUPLE; f->ret_type.flags = TYPE_IS_RESOLVED; - f->ret_type.was_expr = NULL; f->ret_type.tuple = NULL; arr_foreach(f->ret_decls, Declaration, d) { arr_foreach(d->idents, Identifier, i) { @@ -768,7 +760,6 @@ static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement * static Status type_resolve(Typer *tr, Type *t, Location where) { Evaluator *ev = tr->evalr; if (t->flags & TYPE_IS_RESOLVED) return true; - t->was_expr = NULL; switch (t->kind) { case TYPE_ARR: { /* it's an array */ @@ -872,7 +863,6 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { } if (is_tuple_of_types) { t->kind = TYPE_TUPLE; - t->was_expr = expr; t->flags = TYPE_IS_RESOLVED; t->tuple = tuple; break; @@ -901,7 +891,6 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { if (!type_resolve(tr, t, where)) return false; } - t->was_expr = expr; } break; case TYPE_UNKNOWN: case TYPE_VOID: @@ -1571,7 +1560,6 @@ static Status types_expr(Typer *tr, Expression *e) { if (e->flags & EXPR_FOUND_TYPE) return true; Type *t = &e->type; t->flags = TYPE_IS_RESOLVED; - t->was_expr = NULL; t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */ e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ switch (e->kind) { @@ -1597,7 +1585,6 @@ static Status types_expr(Typer *tr, Expression *e) { t->kind = TYPE_SLICE; t->slice = typer_malloc(tr, sizeof *t->slice); t->slice->flags = TYPE_IS_RESOLVED; - t->slice->was_expr = NULL; t->slice->kind = TYPE_BUILTIN; t->slice->builtin = BUILTIN_CHAR; break; @@ -1671,7 +1658,6 @@ static Status types_expr(Typer *tr, Expression *e) { } Type *fo_type = &header->type; fo_type->flags = TYPE_IS_RESOLVED; - fo_type->was_expr = NULL; fo_type->kind = TYPE_TUPLE; fo_type->tuple = fo_type_tuple; @@ -2138,7 +2124,6 @@ static Status types_expr(Typer *tr, Expression *e) { } else { next_type->kind = TYPE_VOID; next_type->flags = TYPE_IS_RESOLVED; - next_type->was_expr = NULL; } if (!type_eq_implicit(next_type, curr_type)) { char *currstr = type_to_str(curr_type); @@ -2682,10 +2667,7 @@ static Status types_expr(Typer *tr, Expression *e) { table_index_type.kind = TYPE_TUPLE; table_index_type.tuple = NULL; Type *u64t = typer_arr_add_ptr(tr, table_index_type.tuple); - u64t->was_expr = NULL; - u64t->flags = TYPE_IS_RESOLVED; - u64t->kind = TYPE_BUILTIN; - u64t->builtin = BUILTIN_U64; + construct_resolved_builtin_type(u64t, BUILTIN_U64); table_index.tuple = NULL; Value *which_are_const_val = typer_arr_add_ptr(tr, table_index.tuple); U64 *which_are_const = &which_are_const_val->u64; @@ -3135,9 +3117,10 @@ static Status types_expr(Typer *tr, Expression *e) { break; } else if (struct_type->kind == TYPE_STRUCT) { StructDef *struc = struct_type->struc; + assert(struc->flags & STRUCT_DEF_RESOLVED); Identifier struct_ident = ident_translate(rhs->ident, &struc->body.idents); - Field *field = NULL; - if (ident_is_declared(struct_ident) && (field = struct_ident->decl->field)) { + if (ident_is_declared(struct_ident) && !(struct_ident->decl->flags & DECL_IS_CONST)) { + Field *field = struct_ident->decl->field; field += ident_index_in_decl(struct_ident, struct_ident->decl); e->binary.dot.field = field; *t = *field->type; @@ -3489,7 +3472,6 @@ static Status types_decl(Typer *tr, Declaration *d) { if (!success) { /* use unknown type if we didn't get the type */ d->type.flags = TYPE_IS_RESOLVED; - d->type.was_expr = NULL; d->type.kind = TYPE_UNKNOWN; } arr_remove_lasta(tr->in_decls, tr->allocr); diff --git a/types.h b/types.h index 92a4a5c..aabf246 100644 --- a/types.h +++ b/types.h @@ -437,7 +437,6 @@ enum { }; typedef U8 TypeFlags; typedef struct Type { - struct Expression *was_expr; /* if non-NULL, indicates that this type used to be an expression (TYPE_EXPR) */ TypeKind kind; TypeFlags flags; union { @@ -507,7 +506,6 @@ enum { typedef struct StructDef { /* these two only exist after resolving (before then, it's scope.stmts) */ Field *fields; - Location where; U8 flags; /* -- cgit v1.2.3