aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c144
-rw-r--r--src/ast.c22
-rw-r--r--src/debug.c2
-rw-r--r--src/lexer.l1
-rw-r--r--src/parser.y16
-rw-r--r--src/scope.c2
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;
diff --git a/src/ast.c b/src/ast.c
index 024cebf..0571c12 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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");