diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/actualize.c | 144 | ||||
| -rw-r--r-- | src/ast.c | 22 | ||||
| -rw-r--r-- | src/debug.c | 2 | ||||
| -rw-r--r-- | src/lexer.l | 1 | ||||
| -rw-r--r-- | src/parser.y | 16 | ||||
| -rw-r--r-- | src/scope.c | 2 |
6 files changed, 134 insertions, 53 deletions
diff --git a/src/actualize.c b/src/actualize.c index 2409162..409480b 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -724,10 +724,12 @@ static int expand_type(struct ast *expd, struct ast *params, struct type *types) { /* we're getting expanded so remove our params to avoid redefining them * later */ - if (expd->k == AST_STRUCT_DEF) - struct_params(expd) = NULL; - else - trait_params(expd) = NULL; + switch (expd->k) { + case AST_STRUCT_DEF: struct_params(expd) = NULL; break; + case AST_STRUCT_CONT_DEF: struct_cont_params(expd) = NULL; break; + case AST_TRAIT_DEF: trait_params(expd) = NULL; break; + default: abort(); + } assert(expd->scope->parent); struct scope *p = expd->scope->parent; @@ -738,10 +740,21 @@ static int expand_type(struct ast *expd, struct ast *params, struct type *types) struct ast *p = clone_ast(n); var_type(p) = clone_type(types); - if (expd->k == AST_STRUCT_DEF) + switch (expd->k) { + case AST_STRUCT_DEF: ast_append(&struct_params(expd), p); - else + break; + + case AST_STRUCT_CONT_DEF: + ast_append(&struct_cont_params(expd), p); + break; + + case AST_TRAIT_DEF: ast_append(&trait_params(expd), p); + break; + + default: abort(); + } types = types->n; } @@ -786,6 +799,50 @@ static struct ast *maybe_expand_struct(struct scope *scope, struct ast *def, return expd; } +static int expand_chain(struct ast *expd, struct ast *params, + struct type *types) +{ + /* bit of a hack for the moment, but start at the bottom of the chain to + * ensure everything gets actualized in the 'correct' order. Might be a + * good idea to instead do some preparations for each node in the chain + * so we can avoid recursion if need be */ + if (expd->chain && expand_chain(expd->chain, params, types)) + return -1; + + return expand_type(expd, params, types); +} + +static struct ast *maybe_expand_struct_cont(struct scope *scope, + struct ast *def, + struct src_loc loc, + struct type *args) +{ + assert(def->k == AST_STRUCT_CONT_DEF); + struct ast *base = chain_base(def); + if (struct_params(base) == NULL) { + if (args == NULL) + return def; + + loc_error(scope->fctx, loc, + "passing types to non-generic struct %s", + struct_id(base)); + return NULL; + } + + struct ast *exists = file_scope_find_expd_struct(scope, base, args); + if (exists) + return exists; + + if (!should_implement_list(scope, struct_params(base), loc, args)) + return NULL; + + struct ast *expd = clone_chain(def); + if (expand_chain(expd, struct_params(base), args)) + return NULL; + + return expd; +} + static struct ast *maybe_expand_trait(struct scope *scope, struct ast *def, struct src_loc loc, struct type *args) { @@ -808,9 +865,14 @@ static struct ast *maybe_expand_trait(struct scope *scope, struct ast *def, static struct ast *maybe_expand_type(struct scope *scope, struct ast *def, struct src_loc loc, struct type *args) { - assert(def->k == AST_STRUCT_DEF || def->k == AST_TRAIT_DEF); + assert( def->k == AST_STRUCT_DEF + || def->k == AST_STRUCT_CONT_DEF + || def->k == AST_TRAIT_DEF); + if (def->k == AST_STRUCT_DEF) return maybe_expand_struct(scope, def, loc, args); + else if (def->k == AST_STRUCT_CONT_DEF) + return maybe_expand_struct_cont(scope, def, loc, args); else return maybe_expand_trait(scope, def, loc, args); } @@ -1319,6 +1381,14 @@ static int actualize_tid(struct act_state *state, struct scope *scope, return -1; } + if (def->k == AST_STRUCT_DEF || def->k == AST_STRUCT_CONT_DEF) { + struct ast *base = chain_base(def); + if (struct_params(base)) { + type_error(scope->fctx, t, "missing type params"); + return -1; + } + } + assert(t->n == NULL); replace_type(t, clone_type_list(def->t)); if (def->k == AST_ALIAS_DEF) @@ -2109,6 +2179,31 @@ static struct ast *chain_lookup(struct act_state *state, struct ast *def, return NULL; } +static int params_match(struct scope *scope, struct ast *base, struct ast *node) +{ + assert(base->k == AST_STRUCT_DEF); + assert(node->k == AST_STRUCT_CONT_DEF); + + struct ast *base_params = struct_params(base); + struct ast *node_params = struct_cont_params(node); + + if (ast_list_len(base_params) != ast_list_len(node_params)) { + semantic_error(scope->fctx, base_params, + "mismatch number of type params"); + return 0; + } + + /** @todo report more accurately what the issue is */ + if (!equiv_nodes(base_params, node_params)) { + semantic_error(scope->fctx, base_params, + "mismatch type params"); + semantic_info(scope->fctx, node_params, "previous"); + return 0; + } + + return 1; +} + static int expand_struct_body(struct act_state *state, struct scope *scope, struct ast *node, @@ -2161,6 +2256,11 @@ static int expand_struct_body(struct act_state *state, return -1; } + if (node->k == AST_STRUCT_CONT_DEF + && !params_match(scope, chain_base(node), node)) { + return -1; + } + if (node->t->k == TYPE_STRUCT) tstruct_params(node->t) = types; @@ -2295,30 +2395,6 @@ static int actualize_struct(struct act_state *state, struct_body(node)); } -static int params_match(struct scope *scope, struct ast *base, struct ast *node) -{ - assert(base->k == AST_STRUCT_DEF); - assert(node->k == AST_STRUCT_CONT_DEF); - - struct ast *base_params = struct_params(base); - struct ast *node_params = struct_cont_params(node); - - if (ast_list_len(base_params) != ast_list_len(node_params)) { - semantic_error(scope->fctx, base_params, - "mismatch number of type params"); - return -1; - } - - /** @todo report more accurately what the issue is */ - if (!equiv_nodes(base_params, node_params)) { - semantic_error(scope->fctx, base_params, - "mismatch type params"); - return -1; - } - - return 0; -} - static int actualize_struct_cont(struct act_state *state, struct scope *scope, struct ast *node) { @@ -2329,9 +2405,6 @@ static int actualize_struct_cont(struct act_state *state, if (actualize(state, scope, up)) return -1; - if (params_match(scope, chain_base(node), node)) - return -1; - return expand_struct_body(state, scope, node, struct_cont_id(node), struct_cont_params(node), @@ -2425,7 +2498,8 @@ static int actualize_init(struct act_state *state, struct vec init_args = vec_create(sizeof(struct init_helper)); struct vec struct_members = vec_create(sizeof(struct init_helper)); - foreach_node(n, struct_body(def)) { + struct ast *base = chain_base(def); + foreach_node(n, struct_body(base)) { if (n->k != AST_VAR_DEF) continue; @@ -699,7 +699,9 @@ static size_t struct_size(struct type *t) return (size_t)t->size; size_t size = 0; - foreach_node(n, struct_body(t->d)) { + + struct ast *base = chain_base(t->d); + foreach_node(n, struct_body(base)) { if (n->k != AST_VAR_DEF) continue; @@ -734,7 +736,8 @@ size_t type_offsetof(struct type *t, char *m) assert(t->k == TYPE_STRUCT); size_t offset = 0; - foreach_node(n, struct_body(t->d)) { + struct ast *base = chain_base(t->d); + foreach_node(n, struct_body(base)) { if (n->k != AST_VAR_DEF) continue; @@ -784,3 +787,18 @@ struct ast *chain_base(struct ast *node) return node; } + +struct ast *clone_chain(struct ast *chain) +{ + if (!chain) + return NULL; + + struct ast *new = clone_ast(chain); + if (!new) + return NULL; + + if (chain->chain) + new->chain = clone_chain(chain->chain); + + return new; +} diff --git a/src/debug.c b/src/debug.c index f91accd..0908ee5 100644 --- a/src/debug.c +++ b/src/debug.c @@ -294,7 +294,7 @@ static void _type_str(FILE *fp, struct type *type) fprintf(fp, "%s", trait_id(def)); } - if (struct_params(def)) { + if (trait_params(def)) { fprintf(fp, "!["); _param_str(fp, trait_params(def)); fprintf(fp, "]"); diff --git a/src/lexer.l b/src/lexer.l index 3d5a413..b110f4c 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -138,7 +138,6 @@ STRING \"(\\.|[^"\\])*\" "pub" {return PUB;} "defer" {return DEFER;} "union" {return UNION;} -"struct" {return STRUCT;} "typedef" {return TYPEDEF;} "import" {return IMPORT;} "sizeof" {return SIZEOF;} diff --git a/src/parser.y b/src/parser.y index c7a3a63..3808807 100644 --- a/src/parser.y +++ b/src/parser.y @@ -75,7 +75,6 @@ %token RSHIFTSELF ">>=" %token COMMA "," %token PUB "pub" -%token STRUCT "struct" %token UNION "union" %token TYPEDEF "typedef" %token IMPORT "import" @@ -778,22 +777,13 @@ struct } struct_cont - : "continue" "[" opt_type_params "]" - APPLY "[" opt_types "]" "{" opt_behaviours "}" { - /* full form */ - $$ = gen_struct_cont($5, $3, $7, $10, src_loc(@$)); - } - | "continue" "[" opt_type_params "]" ID "{" opt_behaviours "}" { - /* abbrev 1 */ - $$ = gen_struct_cont($5, $3, NULL, $7, src_loc(@$)); - } - | "continue" APPLY "[" opt_types "]" "{" opt_behaviours "}" { + : "continue" ID "[" opt_type_params "]" "{" opt_behaviours "}" { /* abbrev 2 */ - $$ = gen_struct_cont($2, NULL, $4, $7, src_loc(@$)); + $$ = gen_struct_cont($2, $4, $7, src_loc(@$)); } | "continue" ID "{" opt_behaviours "}" { /* abbrev 3 */ - $$ = gen_struct_cont($2, NULL, NULL, $4, src_loc(@$)); + $$ = gen_struct_cont($2, NULL, $4, src_loc(@$)); } alias diff --git a/src/scope.c b/src/scope.c index 448c883..198e2c0 100644 --- a/src/scope.c +++ b/src/scope.c @@ -185,7 +185,7 @@ int scope_add_var(struct scope *scope, struct ast *var) int scope_add_type(struct scope *scope, char *id, struct ast *type) { - struct ast *exists = file_scope_find_type(scope, id); + struct ast *exists = scope_find_type(scope, id); if (exists) { semantic_error(scope->fctx, type, "type redefined"); semantic_info(scope->fctx, exists, "previously here"); |
