diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-01-11 00:52:21 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-01-11 00:52:21 +0200 |
| commit | 2d8d5ffaee9701955828413f844afa1b3767f748 (patch) | |
| tree | 0eab7acec6f06b3a4da61a8207dace8524810652 | |
| parent | 2d90cea9adb9a3f73cd5b211a4ed9508b505729f (diff) | |
| download | ek-2d8d5ffaee9701955828413f844afa1b3767f748.tar.gz ek-2d8d5ffaee9701955828413f844afa1b3767f748.zip | |
futher struct continuation work
| -rw-r--r-- | include/ek/ast.h | 6 | ||||
| -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 | ||||
| -rw-r--r-- | tests/struct_generic_cont/source.mk | 1 | ||||
| -rw-r--r-- | tests/struct_generic_cont/struct_generic_cont.ek | 19 |
9 files changed, 157 insertions, 56 deletions
diff --git a/include/ek/ast.h b/include/ek/ast.h index f8ffd8b..2ee9f6f 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -584,10 +584,9 @@ static inline bool is_primitive(struct type *t) #define struct_cont_id(x) return_s(x, AST_STRUCT_CONT_DEF) #define struct_cont_params(x) return_a0(x, AST_STRUCT_CONT_DEF) -#define struct_cont_behav(x) return_t1(x, AST_STRUCT_CONT_DEF) #define struct_cont_body(x) return_a1(x, AST_STRUCT_CONT_DEF) -#define gen_struct_cont(id, params, behav, body, loc) \ - gen_ast(AST_STRUCT_CONT_DEF, params, body, NULL, NULL, behav, id, 0, \ +#define gen_struct_cont(id, params, body, loc) \ + gen_ast(AST_STRUCT_CONT_DEF, params, body, NULL, NULL, NULL, id, 0, \ loc) #define val_id(x) return_s(x, AST_VAL) @@ -746,5 +745,6 @@ struct type *reverse_type_list(struct type *root); for (struct type *iter = nodes; iter; iter = iter->n) struct ast *chain_base(struct ast *node); +struct ast *clone_chain(struct ast *chain); #endif /* AST_H */ 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"); diff --git a/tests/struct_generic_cont/source.mk b/tests/struct_generic_cont/source.mk new file mode 100644 index 0000000..0e856a6 --- /dev/null +++ b/tests/struct_generic_cont/source.mk @@ -0,0 +1 @@ +SIMPLE += struct_generic_cont diff --git a/tests/struct_generic_cont/struct_generic_cont.ek b/tests/struct_generic_cont/struct_generic_cont.ek new file mode 100644 index 0000000..34c604b --- /dev/null +++ b/tests/struct_generic_cont/struct_generic_cont.ek @@ -0,0 +1,19 @@ +define any[] {} +typedef ptr {} +typedef i27 {} + +typedef struct[any T] { + T a; +} + +continue struct[any T] { + do_something(*struct![T] self => T){ + return self*.a; + } +} + +main() +{ + mut p = struct![i27]{.a = 1}; + p.do_something(); +} |
