diff options
-rw-r--r-- | infer.c | 64 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | parse.c | 16 | ||||
-rw-r--r-- | test.toc | 26 | ||||
-rw-r--r-- | toc.c | 2 | ||||
-rw-r--r-- | types.c | 7 | ||||
-rw-r--r-- | types.h | 4 |
7 files changed, 86 insertions, 39 deletions
@@ -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); @@ -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 @@ -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; @@ -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 @@ -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 @@ -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 */ @@ -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; |