diff options
-rw-r--r-- | infer.c | 23 | ||||
-rw-r--r-- | test.toc | 11 | ||||
-rw-r--r-- | types.c | 101 |
3 files changed, 24 insertions, 111 deletions
@@ -4,7 +4,6 @@ You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. */ static bool call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Location where, I16 **orderp); -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, Value to, Type *to_type, Location to_where, Identifier *idents, Value *vals, Type *types) { @@ -41,29 +40,23 @@ static bool infer_from_expr(Typer *tr, Expression *match, Value to, Type *to_typ return false; } Type *fn_type = to.type; - I16 *order; - if (!parameterized_struct_arg_order(fn_type->struc, match->call.args, &order, match->where)) { - free(order); - return false; - } Declaration *params = fn_type->struc->params; - int arg_idx = 0; + Argument *args = match->call.args; + size_t nargs = arr_len(args); + size_t arg_idx = 0; arr_foreach(params, Declaration, param) { int ident_idx = 0; arr_foreach(param->idents, Identifier, i) { - if (order[arg_idx] != -1) { - Expression *arg = &match->call.args[order[arg_idx]].val; - Value val = *decl_val_at_index(param, ident_idx); - if (!infer_from_expr(tr, arg, val, decl_type_at_index(param, ident_idx), param->where, idents, vals, types)) { - free(order); - return false; - } + if (arg_idx >= nargs) break; + Expression *arg = &args[arg_idx].val; + Value val = *decl_val_at_index(param, ident_idx); + if (!infer_from_expr(tr, arg, val, decl_type_at_index(param, ident_idx), param->where, idents, vals, types)) { + return false; } ++arg_idx; ++ident_idx; } } - free(order); } // don't try to match other kinds of function calls. it's impossible to get any information out of it. } break; @@ -2,7 +2,6 @@ #include "std/io.toc", io; #include "std/types.toc"; - write_type ::= fn(f : &File, t :: Type) { k ::= t._kind; use TypeKind; @@ -138,7 +137,7 @@ main ::= fn() { t : [x*x]int; u := &t; v : &void; - p: Point; + p: Point(u8); print_typeof(x); print_typeof(y); @@ -154,11 +153,11 @@ main ::= fn() { xx ::= fn() (int, int) { return 3, 5; } - Point2D ::= struct { - x, y : int; + Point2D ::= struct(t :: Type) { + x, y : t; } - Point ::= struct { - use p: Point2D; + Point ::= struct(t :: Type) { + use p: Point2D(t); z: float; } } @@ -1377,83 +1377,6 @@ static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Lo return true; } -// order must be freed, regardless of return value. if (*order)[i] == -1, that parameter was not set. -static Status parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where) { - size_t nargs = arr_len(args); - - /* - it would be nice if this code and the code for arguments to normal functions - weren't split into two separate functions. - */ - size_t nparams = 0; - arr_foreach(struc->params, Declaration, param) - nparams += arr_len(param->idents); - - *order = err_malloc(nparams * sizeof **order); - - if (nargs > nparams) { - err_print(args[nparams].where, "Expected at most %lu argument%s to parameterized type, but got %lu.", nparams, plural_suffix(nparams), nargs); - return false; - } - for (size_t i = 0; i < nparams; ++i) - (*order)[i] = -1; - int p = 0; // sequential parameter - I16 argno = 0; - - arr_foreach(args, Argument, arg) { - int param_idx; - if (arg->name) { - param_idx = 0; - arr_foreach(struc->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if (ident_eq_str(*ident, arg->name)) - goto struct_params_done; - ++param_idx; - } - } - struct_params_done:; - } else { - param_idx = p; - ++p; - } - if ((*order)[param_idx] != -1) { - Identifier param_name = NULL; - int counter = param_idx; - arr_foreach(struc->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if (--counter < 0) { - param_name = *ident; - break; - } - } - if (param_name) break; - } - - char *s = ident_to_str(param_name); - err_print(arg->where, "Parameter #%d (%s) set twice in parameterized type instantiation.", param_idx+1, s); - free(s); - return false; - } - (*order)[param_idx] = argno; - ++argno; - } - - p = 0; - arr_foreach(struc->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if ((*order)[p] == -1 && !(param->flags & DECL_HAS_EXPR)) { - char *s = ident_to_str(*ident); - err_print(where, "Parameter #%d (%s) not set in parameterized struct instantiation.", p+1, s); - free(s); - return false; - } - ++p; - } - } - - return true; -} - static Value get_builtin_val(GlobalCtx *gctx, BuiltinVal val) { Value v; switch (val) { @@ -1884,12 +1807,6 @@ static Status types_expr(Typer *tr, Expression *e) { bool already_exists; Value args_val = {0}; Type args_type = {0}; - I16 *order; - // get proper order of arguments (some of them might be named, etc.) - if (!parameterized_struct_arg_order(&struc, c->args, &order, e->where)) { - free(order); - return false; - } Type *arg_types = NULL; arr_set_len(arg_types, nparams); // needs to stay around because the instance table keeps a reference to it (if it hasn't already been added) @@ -1909,15 +1826,20 @@ static Status types_expr(Typer *tr, Expression *e) { arr_remove_last(err_ctx->instance_stack); tr->block = prev; if (!success) return false; - + Argument *args = c->args; + size_t arg_idx = 0, nargs = arr_len(args); arr_foreach(param->idents, Identifier, ident) { Type *type = decl_type_at_index(param, ident_idx); arg_types[p] = *type; Value ident_val; - if (order[p] == -1) { + if (arg_idx >= nargs) { ident_val = *decl_val_at_index(param, ident_idx); } else { - Argument *arg = &c->args[order[p]]; + Argument *arg = &args[arg_idx++]; + if (arg->name) { + err_print(arg->where, "struct arguments can't be named."); + return false; + } assert(arg->val.type.flags & TYPE_IS_RESOLVED); assert(type->flags & TYPE_IS_RESOLVED); if (!type_eq_implicit(&arg->val.type, type)) { @@ -1940,7 +1862,6 @@ static Status types_expr(Typer *tr, Expression *e) { param->val = param_val; param->flags |= DECL_FOUND_VAL; } - free(order); args_val.tuple = arg_vals; args_type.tuple = arg_types; args_type.kind = TYPE_TUPLE; @@ -2958,7 +2879,7 @@ static Status types_expr(Typer *tr, Expression *e) { } } } else if (ltype->kind == TYPE_STRUCT) { - e->val.boolv = ltype->struc->params != NULL; + e->val.boolv = struct_is_template(ltype->struc); } else { err_print(e->where, "This type doesn't have a '_is_template' member (only functions and structs do)."); return false; @@ -2984,7 +2905,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } StructDef *struc = ltype->struc; - if (struc->params) { + if (struct_is_template(struc)) { err_print(e->where, "You can't access the '_member_names' type information from a struct template."); return false; } @@ -3019,7 +2940,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } StructDef *struc = ltype->struc; - if (struc->params) { + if (struct_is_template(struc)) { err_print(e->where, "You can't access the '_member_types' type information from a struct template."); return false; } |