summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-20 14:39:44 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-20 14:39:44 -0500
commit9055d35ad80f804e4bfb5ef9968b25dad92f3764 (patch)
treedc74c6b237203a038bcfa338580dcd6c7d4a7e98
parentcfc2e1f3841785ee7466240913f6b13797fb4760 (diff)
fixing default arguments for parameterized structs
-rw-r--r--infer.c50
-rw-r--r--main.c3
-rw-r--r--test.toc42
-rw-r--r--types.c131
4 files changed, 127 insertions, 99 deletions
diff --git a/infer.c b/infer.c
index ff875dc..3f2291d 100644
--- a/infer.c
+++ b/infer.c
@@ -25,27 +25,43 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres
break;
case EXPR_CALL: {
#if 0
- /* TODO: infer from parameterized structs */
- size_t nargs = arr_len(match->struc.args);
- Declaration *param = to->struc->params;
- int ident_idx = 0;
- for (i = 0; i < nargs; ++i) {
- Expression *arg = &match->struc.args[i];
- 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, &val_expr, idents, vals, types)) {
+ if (to->kind == EXPR_TYPE) {
+ /* maybe it's a parameterized struct? */
+ /* it might not be possible that it's not, but might as well keep that possibility around. */
+ Value fn_val = {0};
+ if (!types_expr(tr, match->call.fn)) {
return false;
}
- ++ident_idx;
- if (ident_idx >= (int)arr_len(param->idents)) {
- ++param;
- ident_idx = 0;
+ if (type_is_builtin(&match->call.fn->type, BUILTIN_TYPE)) {
+ /* it's a parameterized struct */
+ if (!eval_expr(tr->evalr, match->call.fn, &fn_val)) {
+ return false;
+ }
+ assert(fn_val.type->kind == TYPE_STRUCT);
+
+ size_t nargs = arr_len(match->call.args);
+ Declaration *param = fn_val.type->struc->params;
+ int ident_idx = 0;
+ for (size_t i = 0; i < nargs; ++i) {
+ Expression *arg = &match->call.args[i];
+ 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, &val_expr, idents, vals, types)) {
+ return false;
+ }
+ ++ident_idx;
+ if (ident_idx >= (int)arr_len(param->idents)) {
+ ++param;
+ ident_idx = 0;
+ }
+ }
}
}
+
#endif
while (to->kind == EXPR_IDENT) {
diff --git a/main.c b/main.c
index 7f078d8..1c6d7d8 100644
--- a/main.c
+++ b/main.c
@@ -20,8 +20,9 @@
TODO:
struct parameters
- make sure inference works with struct params
+- split up a,b::int for parameterized structs (?also maybe normal parameters?)
- allow accessing parameters with .
-- should argument set twice error be in call_arg_param_order?
+- make call_arg_param_order work more like parameterized_struct_arg_order
---
see infer.c "is resolved_to necessary" (now that ident system has changed)
replace is_reference in type_resolve_ with system for checking if type is
diff --git a/test.toc b/test.toc
index d56944a..e115d6b 100644
--- a/test.toc
+++ b/test.toc
@@ -1,41 +1,11 @@
-io ::= nms {
-#include "std/io.toc";
-};
-
-LinkedList ::= struct(t::Type) {
- head : t;
- tail : &LinkedList(t);
-};
-
-arr_to_ll ::= fn(t::Type, data: []t) l : LinkedList(t) {
- if data.len == 1 {
- l.head = data[0];
- l.tail = 0 as &LinkedList(t);
- } else {
- l.head = data[0];
- l.tail = new(LinkedList(t));
- *l.tail = arr_to_ll(t, data[1:]);
- }
-};
-
-do_thing ::= fn() int {
+// io ::= nms {
+// #include "std/io.toc";
+// };
- a := new(int, 3);
- a[0] = 10;
- a[1] = 20;
- a[2] = 30;
- x := arr_to_ll(int, a);
- p := &x;
- i := 0;
- while p {
- io.puti(p.head);
- p = p.tail;
- i += 1;
- }
- i
+Thing ::= struct(t::Type=int) {
+ it : t;
};
main ::= fn() {
- x ::= do_thing();
- do_thing();
+ a: Thing();
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 56adeb8..28a59c2 100644
--- a/types.c
+++ b/types.c
@@ -956,6 +956,61 @@ static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Type *fn_type, A
return true;
}
+/* *order must be freed, regardless of return value. if (*order)[i] == -1, that parameter was not set. */
+static bool parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order) {
+ /*
+ 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);
+ for (size_t i = 0; i < nparams; ++i)
+ (*order)[i] = -1;
+ int p = 0; /* sequential parameter */
+
+
+ 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)[arg - args] = (I16)param_idx;
+ }
+ return true;
+}
+
static Value get_builtin_val(BuiltinVal val) {
Value v;
switch (val) {
@@ -1435,61 +1490,48 @@ static bool types_expr(Typer *tr, Expression *e) {
err_print(e->where, "Expected at most %lu argument%s to parameterized type, but got %lu.", nparams, plural_suffix(nparams), nargs);
return false;
}
-
- /*
- it would be nice if this code and the code for arguments to normal functions
- used the same stuff for named arguments, etc.
- */
- Value *arg_vals = typer_malloc(tr, nparams * sizeof *arg_vals);
+ HashTable *table = &base->struc->instances;
+ bool already_exists;
+ Value args_val = {0};
+ Type args_type = {0};
+ I16 *order;
+ if (!parameterized_struct_arg_order(base->struc, c->args, &order)) {
+ free(order);
+ return false;
+ }
Type *arg_types = NULL;
arr_set_len(&arg_types, nparams);
- U8 *params_set = err_calloc(1, nparams);
- int p = 0; /* sequential parameter */
+ Value *arg_vals = typer_malloc(tr, nparams * sizeof *arg_vals);
- arr_foreach(c->args, Argument, arg) {
- int param_idx;
- if (arg->name) {
- param_idx = 0;
- arr_foreach(base->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 (params_set[param_idx]) {
- Identifier param_name = NULL;
- int counter = param_idx;
+ for (size_t i = 0; i < nparams; ++i) {
+ if (order[i] == -1) {
+ Declaration *ith_parameter = NULL;
+ int index_in_decl = -1;
+ size_t i_copy = i;
+ /* fetch ith parameter */
arr_foreach(base->struc->params, Declaration, param) {
arr_foreach(param->idents, Identifier, ident) {
- if (--counter < 0) {
- param_name = *ident;
+ if (i_copy == 0) {
+ /* here we are */
+ ith_parameter = param;
+ index_in_decl = (int)(ident - param->idents);
break;
}
+ --i_copy;
}
- 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;
+ assert(ith_parameter);
+ arg_types[i] = *decl_type_at_index(ith_parameter, index_in_decl);
+ arg_vals[i] = *decl_val_at_index(ith_parameter, index_in_decl);
+ } else {
+ Argument *arg = &c->args[order[i]];
+ arg_types[i] = arg->val.type;
+ if (!eval_expr(tr->evalr, &arg->val, &arg_vals[i]))
+ return false;
}
- params_set[param_idx] = true;
- arg_types[param_idx] = arg->val.type;
- if (!eval_expr(tr->evalr, &arg->val, &arg_vals[param_idx]))
- return false;
+ assert(arg_types[i].flags & TYPE_IS_RESOLVED);
}
-
- HashTable *table = &base->struc->instances;
- bool already_exists;
- Value args_val = {0};
- Type args_type = {0};
+
args_val.tuple = arg_vals;
args_type.tuple = arg_types;
args_type.kind = TYPE_TUPLE;
@@ -1531,7 +1573,6 @@ static bool types_expr(Typer *tr, Expression *e) {
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_TYPE;
arr_clear(&arg_types);
- free(params_set);
goto ret;
}
fn_decl = val.fn;