summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--infer.c64
-rw-r--r--main.c6
-rw-r--r--parse.c16
-rw-r--r--test.toc26
-rw-r--r--toc.c2
-rw-r--r--types.c7
-rw-r--r--types.h4
7 files changed, 86 insertions, 39 deletions
diff --git a/infer.c b/infer.c
index 35760fa..08ffd1b 100644
--- a/infer.c
+++ b/infer.c
@@ -1,9 +1,18 @@
static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Type *fn_type, Argument *args, Location where, U16 **param_indices);
+static bool parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where);
static bool types_expr(Typer *tr, Expression *e);
/* resolved_to should have the same value as to, but not consist of any identifiers which aren't in scope right now */
/* TODO: is resolved_to necessary? */
static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expression *resolved_to, Identifier *idents, Value *vals, Type *types) {
+#if 0
+ printf("Matching ");
+ fprint_expr(stdout, match);
+ printf(" to ");
+ fprint_expr(stdout, to);
+ printf("\n");
+#endif
+
assert(!(match->flags & EXPR_FOUND_TYPE));
assert(to->flags & EXPR_FOUND_TYPE);
switch (match->kind) {
@@ -24,6 +33,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres
}
break;
case EXPR_CALL: {
+
if (to->kind == EXPR_TYPE && to->typeval.kind == TYPE_STRUCT) {
/* maybe it's a parameterized struct? */
/* it might not be possible that it's not, but might as well keep that possibility around. */
@@ -40,32 +50,35 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres
assert(fn_val.type->kind == TYPE_STRUCT);
I16 *order;
- if (!parameterized_type_arg_order(tr, &order, match->where))
+ if (!parameterized_struct_arg_order(fn_val.type->struc, match->call.args, &order, match->where)) {
+ free(order);
return false;
-
- size_t nargs = arr_len(match->call.args);
- Declaration *param = to->typeval.struc->params;
- int ident_idx = 0;
- for (size_t i = 0; i < nargs; ++i) {
- Expression *arg = &match->call.args[i].val;
- Value val = arr_len(param->idents) > 1 ? param->val.tuple[ident_idx] : param->val;
- 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;
+ }
+ Declaration *params = to->typeval.struc->params;
+ int 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);
+ 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)) {
+ free(order);
+ return false;
+ }
+ }
+ ++arg_idx;
+ ++ident_idx;
}
}
+ free(order);
}
}
-
while (to->kind == EXPR_IDENT) {
Identifier i = to->ident;
@@ -83,7 +96,14 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres
if (expr) to = expr;
} else break;
}
- if (to->kind != EXPR_CALL) return true; /* give up */
+ if (to->kind != EXPR_CALL) {
+ if (to->kind == EXPR_TYPE) {
+ to = to->typeval.was_expr;
+ }
+ if (!to || to->kind != EXPR_CALL)
+ return true; /* give up */
+ }
+
Argument *m_args = match->call.args;
Expression *t_args = to->call.arg_exprs;
size_t nargs = arr_len(m_args);
diff --git a/main.c b/main.c
index 886599b..e0c3a11 100644
--- a/main.c
+++ b/main.c
@@ -18,8 +18,7 @@
/*
TODO:
-- make sure inference works with struct params
-- split up a,b::int for parameterized structs (?also maybe normal parameters?)
+- split up a,b::int for parameterized structs (?also maybe normal const parameters?)
- allow accessing parameters with .
- make call_arg_param_order work more like parameterized_struct_arg_order
@@ -89,7 +88,8 @@ int main(int argc, char **argv) {
#ifdef TOC_DEBUG
signal(SIGABRT, signal_handler);
signal(SIGSEGV, signal_handler);
-
+#endif
+#ifdef RUN_TESTS
test_all();
#endif
diff --git a/parse.c b/parse.c
index b7b2ce6..a0ed884 100644
--- a/parse.c
+++ b/parse.c
@@ -898,6 +898,18 @@ static bool parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end
++t->token;
break;
}
+ if (decl->flags & DECL_INFER) {
+ /* split this declaration */
+ size_t nidents = arr_len(decl->idents);
+ for (size_t i = 1; i < nidents; ++i) {
+ Declaration *new_decl = parser_arr_add(p, decls);
+ *new_decl = *decl;
+ new_decl->idents = NULL;
+ arr_set_lena(&new_decl->idents, 1, p->allocr);
+ new_decl->idents[0] = decl->idents[i];
+ }
+ arr_set_lena(&decl->idents, 1, p->allocr);
+ }
}
return ret;
}
@@ -2009,10 +2021,6 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
} else if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
/* inferred expression */
d->flags |= DECL_INFER;
- if (arr_len(d->idents) > 1) {
- tokr_err(t, "Inferred declarations can only have one identifier. Please separate this declaration.");
- goto ret_false;
- }
if (!(d->flags & DECL_IS_CONST)) {
tokr_err(t, "Inferred parameters must be constant.");
goto ret_false;
diff --git a/test.toc b/test.toc
index ff5f1d3..c9ef4b3 100644
--- a/test.toc
+++ b/test.toc
@@ -1,6 +1,6 @@
-// io ::= nms {
-// #include "std/io.toc";
-// };
+io ::= nms {
+#include "std/io.toc";
+};
@@ -9,12 +9,26 @@ Thing ::= struct(t::=int, u::t=3) {
that : [u]t;
};
-f ::= fn(t::=,u::=,th : Thing(t,u)) {
+f ::= fn(t,u::=,th : &Thing(t,u)) {
x: t = 17 as t;
th.it = x;
+ for p, i := &th.that {
+ *p = i as t;
+ }
+};
+
+print_thing ::= fn(t, u::=, th: Thing(t, u)) {
+ io.puti(th.it as int);
+ for x := th.that {
+ io.puti(x as int);
+ }
};
main ::= fn() {
- a: Thing(u = 172, t = u8);
- f(a);
+ a: Thing(u = 5, t = u8);
+ f(&a);
+ print_thing(a);
+ b: Thing();
+ f(&b);
+ print_thing(b);
}; \ No newline at end of file
diff --git a/toc.c b/toc.c
index 1f5ef0e..3502986 100644
--- a/toc.c
+++ b/toc.c
@@ -127,7 +127,7 @@ static bool cgen_sdecls_file(CGenerator *g, ParsedFile *f);
#include "sdecls_cgen.c"
#include "decls_cgen.c"
-#ifdef TOC_DEBUG
+#ifdef RUN_TESTS
#include "tests.c"
#endif
diff --git a/types.c b/types.c
index 1435390..db2f2e2 100644
--- a/types.c
+++ b/types.c
@@ -1472,6 +1472,7 @@ static bool types_expr(Typer *tr, Expression *e) {
CallExpr *c = &e->call;
c->instance = NULL;
Expression *f = c->fn;
+ Copier cop = {0};
FnExpr *fn_decl = NULL;
if (!types_expr(tr, f)) return false;
arr_foreach(c->args, Argument, arg) {
@@ -1507,7 +1508,7 @@ static bool types_expr(Typer *tr, Expression *e) {
info_print(base->struc->where, "struct was declared here.");
return false;
}
- Copier cop = copier_create(tr->allocr, tr->block);
+ cop = copier_create(tr->allocr, tr->block);
HashTable *table = &base->struc->instances;
StructDef struc;
copy_struct(&cop, &struc, base->struc);
@@ -1606,6 +1607,8 @@ static bool types_expr(Typer *tr, Expression *e) {
inst->struc.instance_id = table->n;
}
+
+
/* expression is actually a type */
e->kind = EXPR_TYPE;
memset(&e->typeval, 0, sizeof e->typeval);
@@ -1713,7 +1716,7 @@ static bool types_expr(Typer *tr, Expression *e) {
Type table_index_type = {0};
Value table_index = {0};
FnExpr *fn_copy = NULL;
- Copier cop = copier_create(tr->allocr, tr->block);
+ cop = copier_create(tr->allocr, tr->block);
if (fn_type->constness) {
/* evaluate compile-time arguments + add an instance */
diff --git a/types.h b/types.h
index 18836bf..a6e49dc 100644
--- a/types.h
+++ b/types.h
@@ -709,11 +709,13 @@ enum {
EXPR_FOUND_TYPE = 0x01
};
+typedef U8 ExprFlags;
+
typedef struct Expression {
Type type;
Location where;
ExprKind kind : 8;
- U8 flags;
+ ExprFlags flags;
struct {
IdentID id; /* cgen ID used for this expression */
} cgen;