aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c357
-rw-r--r--src/compiler.c67
-rw-r--r--src/lower.c44
-rw-r--r--src/parser.y6
-rw-r--r--src/scope.c40
5 files changed, 241 insertions, 273 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 9e36553..11c8db7 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -491,14 +491,19 @@ static struct ast *analyze_type_expand(struct scope *scope,
return body;
}
-static int has_trait(struct ast *body, char *id)
+static int has_trait(struct ast *body, struct ast *expand)
{
+ assert(expand->k == AST_TYPE_EXPAND);
foreach_node(n, body) {
- /* traits don't currently take generic parameters I guess? */
- if (n->k != AST_ID)
+ /* ignore trait parameters for now */
+ if (n->k != AST_TYPE_EXPAND)
+ continue;
+
+ /* ignore ourselves */
+ if (n == expand)
continue;
- if (same_id(id_str(n), id))
+ if (same_id(type_expand_id(n), type_expand_id(expand)))
return -1;
}
@@ -739,7 +744,8 @@ static int reset(struct ast *body)
return ast_visit(_reset, NULL, body, NULL);
}
-static int expand_type(struct ast *expd, struct ast *params, struct type *types)
+static int expand_type(struct scope *scope, struct ast *expd,
+ struct ast *params, struct type *types)
{
/* we're getting expanded so remove our params to avoid redefining them
* later */
@@ -750,9 +756,6 @@ static int expand_type(struct ast *expd, struct ast *params, struct type *types)
default: abort();
}
- assert(expd->scope->parent);
- struct scope *p = expd->scope->parent;
-
reset(expd);
foreach_node(n, params) {
@@ -782,7 +785,7 @@ static int expand_type(struct ast *expd, struct ast *params, struct type *types)
* will succeed (and I guess we wouldn't need to actualize anything) but
* this seems like the simplest solution for now */
struct act_state state = {0};
- int ret = actualize(&state, p, expd);
+ int ret = actualize(&state, scope, expd);
assert(ret == 0);
printf("\n//expanded:\n");
@@ -812,43 +815,27 @@ static struct ast *maybe_expand_struct(struct scope *scope, struct ast *def,
return NULL;
struct ast *expd = clone_ast(def);
- if (expand_type(expd, struct_params(def), args))
+ if (scope_add_expd_struct(scope, def, args, expd))
+ return NULL;
+
+ if (expand_type(scope, expd, struct_params(def), args))
return NULL;
return expd;
}
-static int expand_chain(struct ast *expd, struct ast *params,
+static int expand_chain(struct scope *scope, 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))
+ if (expd->chain && expand_chain(scope, expd->chain, params, types))
return -1;
- return expand_type(expd, params, types);
-}
-
-static struct ast *chain_graft(struct ast *exists, struct ast *def,
- struct ast *params, struct type *types)
-{
- if (same_src(exists, def))
- return exists;
-
- assert(def->chain);
- struct ast *graft = chain_graft(exists, def->chain, params, types);
- if (!graft)
- return NULL;
-
- struct ast *new = clone_ast(def);
- new->chain = graft;
-
- if (expand_type(new, params, types))
- return NULL;
-
- return new;
+ return expand_type(scope, expd, params, types);
}
static struct ast *maybe_expand_struct_cont(struct scope *scope,
@@ -868,15 +855,18 @@ static struct ast *maybe_expand_struct_cont(struct scope *scope,
return NULL;
}
- struct ast *exists = file_scope_find_expd_struct(scope, base, args);
+ struct ast *exists = file_scope_find_expd_struct(scope, def, args);
if (exists)
- return chain_graft(exists, def, struct_params(base), args);
+ 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))
+ if (scope_add_expd_chain(scope, def, args, expd))
+ return NULL;
+
+ if (expand_chain(scope, expd, struct_params(base), args))
return NULL;
return expd;
@@ -1017,48 +1007,36 @@ static int simplify_refderef(struct act_state *state, struct scope *scope,
return 0;
}
-/* not really ufcs at the moment */
-static int maybe_ufcs(struct act_state *state, struct scope *scope,
- struct ast *call)
+static int use_ufcs(struct ast *call)
{
assert(call->k == AST_CALL);
struct ast *dot = call_expr(call);
if (dot->k != AST_DOT)
- return 0;
+ return false;
- struct type *ptypes = callable_ptypes(dot->t);
+ /** @todo does this still work with function pointers? */
struct ast *expr = dot_expr(dot);
- char *id = strdup(dot_id(dot));
- call_expr(call) = gen_fetch(id, clone_type(expr->t), dot->loc);
- (call_expr(call))->t = clone_type(dot->t);
- (call_expr(call))->scope = scope;
-
- struct ast *ref = NULL;
+ struct type *type = expr->t;
+ if (dot->t->k != TYPE_CALLABLE)
+ return false;
+ struct type *ptypes = callable_ptypes(dot->t);
if (!ptypes) {
- ref = NULL;
+ ast_set_flags(call, AST_FLAG_UFCS_TRIVIAL);
+ return true;
}
- else if (ptypes->k == TYPE_PTR) {
- /* is ufcs expects reference to member, try to take address */
- ref = gen_unop(AST_REF, expr, dot->loc);
- ref->t = tgen_ptr(clone_type(expr->t), dot->loc);
- if (actualize_type(state, scope, ref->t))
- return -1;
- ref->scope = scope;
- }
- else {
- /* otherwise, try to pass expr as is */
- ref = expr;
+ if (types_match(ptypes, type)) {
+ ast_set_flags(call, AST_FLAG_UFCS_SIMPLE);
+ return true;
}
- if (ref && simplify_refderef(state, scope, ref))
- return -1;
-
- if (ref)
- call_args(call) = ast_prepend(call_args(call), ref);
+ if (ptypes->k == TYPE_PTR && types_match(ptr_base(ptypes), type)) {
+ ast_set_flags(call, AST_FLAG_UFCS_REF);
+ return true;
+ }
- return 0;
+ return false;
}
static int actualize_call(struct act_state *state,
@@ -1073,23 +1051,28 @@ static int actualize_call(struct act_state *state,
return -1;
struct ast *expr = call_expr(call);
- if (expr->t->k != TYPE_CALLABLE) {
- char *tstr = type_str(expr->t);
+ struct type *type = expr->t;
+ if (type->k == TYPE_PTR)
+ type = ptr_base(type);
+
+ if (type->k != TYPE_CALLABLE) {
+ char *tstr = type_str(type);
semantic_error(scope->fctx, call, "not a callable type: %s",
tstr);
free(tstr);
return -1;
}
- if (maybe_ufcs(state, scope, call))
- return -1;
-
- struct type *callable = expr->t;
+ struct type *callable = type;
struct type *ptypes = callable_ptypes(callable);
struct ast *arg = call_args(call);
+
+ if (use_ufcs(call) && ptypes)
+ ptypes = ptypes->n;
+
foreach_type(p, ptypes) {
if (!arg) {
- semantic_error(scope->fctx, call, "too many arguments");
+ semantic_error(scope->fctx, call, "too few arguments");
return -1;
}
@@ -2040,25 +2023,28 @@ static int _replace_type_id(struct type *type, void *data)
break;
}
- case TYPE_TRAIT: {
- struct ast *def = type->d;
- assert(def);
+ /* these shouldn't actually even be here?
+ case TYPE_TRAIT: {
+ struct ast *def = type->d;
+ assert(def);
- char *name = trait_id(def);
- if (same_id(id, name))
- replace_type(type, clone_type(replacement));
- break;
- }
+ char *name = trait_id(def);
+ if (same_id(id, name))
+ replace_type(type, clone_type(replacement));
- case TYPE_STRUCT: {
- struct ast *def = type->d;
- assert(def);
+ break;
+ }
- char *name = struct_id(def);
- if (same_id(id, name))
- replace_type(type, clone_type(replacement));
- break;
- }
+ case TYPE_STRUCT: {
+ struct ast *def = type->d;
+ assert(def);
+
+ char *name = struct_id(def);
+ if (same_id(id, name))
+ replace_type(type, clone_type(replacement));
+ break;
+ }
+ */
default:
break;
@@ -2103,107 +2089,6 @@ static int clear_scope(struct ast *nodes)
return ast_visit(_clear_scope, NULL, nodes, NULL);
}
-
-/* lots of overlap with actualize_struct, kind of ugly... */
-static int actualize_trait(struct act_state *state, struct scope *scope,
- struct ast *node)
-{
- UNUSED(state);
- assert(node->k == AST_TRAIT_DEF);
- struct ast *params = trait_params(node);
- struct scope *trait_scope = create_scope();
- if (!trait_scope)
- return -1;
-
- scope_add_scope(node->scope, trait_scope);
- node->scope = trait_scope;
-
- /** @todo should probably add in aliases for the traits in scope? */
- if (params)
- ast_set_flags(node, AST_FLAG_GENERIC);
-
- char *id = trait_id(node);
- node->t = tgen_trait(strdup(id), node, node->loc);
-
- /* copy body */
- node->a2 = clone_ast(trait_raw_body(node));
-
- /* do type expansions */
- foreach_node(n, trait_body(node)) {
- if (n->k != AST_TYPE_EXPAND)
- continue;
-
- /* don't re-expand already implemented traits */
- if (has_trait(trait_body(node), type_expand_id(n))) {
- /* not sure about this, but at least we don't have stray
- * type expands everywhere */
- n->k = AST_EMPTY;
- continue;
- }
-
- if (same_id(trait_id(node), type_expand_id(n))) {
- semantic_error(scope->fctx, n,
- "recursive trait implementations not allowed");
- return -1;
- }
-
- struct ast *body = analyze_type_expand(scope, n);
- if (!body) {
- n->k = AST_EMPTY;
- continue;
- }
-
- replace_type_id(body, type_expand_id(n), node->t);
- clear_scope(body);
-
- ast_last(body)->n = n->n;
- n->n = body;
- }
-
-
- /** @todo I should really check that there's just one prototype and one
- * implementation of that prototype, not sure what the best approach
- * would be. Add a prototypes -list to scopes? */
-
- /* add all prototypes that don't have matching definition to scope */
- foreach_node(n, trait_body(node)) {
- if (n->k == AST_TYPE_EXPAND)
- continue;
-
- if (n->k == AST_PROC_DEF && !proc_body(n))
- continue;
-
- if (analyze_visibility(trait_scope, n))
- return -1;
-
- struct act_state state = {0};
- if (actualize(&state, trait_scope, n))
- return -1;
- }
-
- foreach_node(n, trait_body(node)) {
- /* 'actualize' prototypes to make them appear in scope searches
- * */
- if (n->k != AST_PROC_DEF)
- continue;
-
- if (proc_body(n))
- continue;
-
- struct ast *exists = scope_find_proc(trait_scope, proc_id(n));
- if (exists)
- continue;
-
- if (analyze_visibility(trait_scope, n))
- return -1;
-
- if (actualize_proc_sign(trait_scope, n))
- return -1;
- }
-
- return node->t == NULL;
-}
-
static struct ast *chain_lookup(struct act_state *state, struct ast *def,
char *id)
{
@@ -2262,8 +2147,14 @@ static int expand_struct_body(struct act_state *state,
if (params)
ast_set_flags(node, AST_FLAG_GENERIC);
+ /* clone raw body */
+ node->a2 = clone_ast_list(body);
+ body = node->a2;
+
/* do type setting first to make sure body checking works */
- if (same_id(id, "i27"))
+ if (node->k == AST_TRAIT_DEF)
+ node->t = tgen_trait(strdup(id), node, node->loc);
+ else if (same_id(id, "i27"))
node->t = tgen_primitive(TYPE_I27, strdup(id), node, node->loc);
else if (same_id(id, "i9"))
node->t = tgen_primitive(TYPE_I9, strdup(id), node, node->loc);
@@ -2306,23 +2197,19 @@ static int expand_struct_body(struct act_state *state,
if (node->t->k == TYPE_STRUCT)
tstruct_params(node->t) = types;
- struct ast *def = file_scope_find_type(scope, id);
- struct ast *base = chain_base(def);
-
int ret = 0;
- if (node->k == AST_STRUCT_DEF)
- ret = scope_add_expd_struct(scope, base, types, node);
- else if (node->k == AST_STRUCT_CONT_DEF)
- ret = scope_add_expd_chain(scope, base, types, node);
- else
- abort();
+ switch (node->k) {
+ case AST_STRUCT_DEF: ret = scope_add_expd_struct(scope, node, types,
+ node); break;
+ case AST_STRUCT_CONT_DEF: ret = scope_add_expd_chain(scope, node, types,
+ node); break;
+ case AST_TRAIT_DEF: break;
+ default: abort();
+ }
assert(ret == 0);
foreach_node(n, body) {
- if (n->k != AST_TYPE_EXPAND)
- continue;
-
/** @todo when I eventually implement continuing structure
* definitions I might add the primitive types by default to
* structs, that way we don't need this check or the above type
@@ -2333,9 +2220,13 @@ static int expand_struct_body(struct act_state *state,
return -1;
}
- if (has_trait(body, type_expand_id(n))) {
- n->k = AST_EMPTY;
+ if (n->k != AST_TYPE_EXPAND)
continue;
+
+ if (has_trait(body, n)) {
+ semantic_error(scope->fctx, n,
+ "reimplementation of trait");
+ return -1;
}
if (same_id(id, type_expand_id(n))) {
@@ -2357,6 +2248,16 @@ static int expand_struct_body(struct act_state *state,
n->n = body;
}
+ /* add prototypes */
+ foreach_node(n, body) {
+ if (!(n->k == AST_PROC_DEF && !proc_body(n)))
+ continue;
+
+ if (analyze_visibility(struct_scope, n))
+ return -1;
+ }
+
+ /* add implementations/variables */
foreach_node(n, body) {
/* don't actually actualize type expansion for now, it's just
* sticking around to make it easier to check if a type
@@ -2365,11 +2266,10 @@ static int expand_struct_body(struct act_state *state,
if (n->k == AST_TYPE_EXPAND)
continue;
- /* prototypes are handled separately */
if (n->k == AST_PROC_DEF && !proc_body(n))
continue;
- if (n->k == AST_PROC_DEF) {
+ if (n->k == AST_PROC_DEF && proc_body(n)) {
struct ast *prev = chain_lookup(state, node->chain,
proc_id(n));
if (prev) {
@@ -2388,15 +2288,14 @@ static int expand_struct_body(struct act_state *state,
if (n->k == AST_TYPE_EXPAND)
continue;
- /* prototypes are (still) handled separately */
- if (n->k == AST_PROC_DEF && !proc_body(n))
- continue;
-
struct act_state state = {0};
if (actualize(&state, struct_scope, n))
return -1;
}
+ if (node->k == AST_TRAIT_DEF)
+ return 0;
+
/* check that all prototypes are implemented */
foreach_node(n, body) {
if (n->k != AST_PROC_DEF)
@@ -2422,8 +2321,6 @@ static int expand_struct_body(struct act_state *state,
}
}
- /** @todo there is the possibility that two different traits add the
- * same prototype, which is reported in traits but not structs? */
return 0;
}
@@ -2433,29 +2330,15 @@ static int actualize_struct(struct act_state *state,
UNUSED(state);
assert(node->k == AST_STRUCT_DEF);
return expand_struct_body(state, scope, node,
- struct_id(node), struct_params(node),
- struct_body(node));
+ struct_id(node),
+ struct_params(node),
+ struct_raw_body(node));
}
static int actualize_struct_cont(struct act_state *state,
struct scope *scope, struct ast *node)
{
assert(node->k == AST_STRUCT_CONT_DEF);
- struct ast *base = chain_base(node);
- assert(base);
-
- /** @todo this is arguably kind of a hack to sidestep issues
- * with 'which implementation of this trait should be used', but
- * it kind of has some nice properties in and of itself, will
- * have to think about this a bit more. */
- if (ast_flags(node, AST_FLAG_PUBLIC) != ast_flags(base, AST_FLAG_PUBLIC)) {
- /** @todo should the error report mention that this is possibly
- * a temporary hack? */
- semantic_error(scope->fctx, node, "different publicity flags than base");
- semantic_info(scope->fctx, base, "previous here");
- return -1;
- }
-
struct ast *up = node->chain;
assert(up);
@@ -2465,7 +2348,17 @@ static int actualize_struct_cont(struct act_state *state,
return expand_struct_body(state, scope, node,
struct_cont_id(node),
struct_cont_params(node),
- struct_cont_body(node));
+ struct_cont_raw_body(node));
+}
+
+static int actualize_trait(struct act_state *state, struct scope *scope,
+ struct ast *node)
+{
+ assert(node->k == AST_TRAIT_DEF);
+ return expand_struct_body(state, scope, node,
+ trait_id(node),
+ trait_params(node),
+ trait_raw_body(node));
}
static int actualize_dot(struct act_state *state,
@@ -2516,8 +2409,8 @@ static int actualize_dot(struct act_state *state,
char *tstr = type_str(type);
semantic_error(scope->fctx, node,
- "%s does not have member",
- tstr);
+ "%s does not have member '%s'",
+ tstr, id);
free(tstr);
return -1;
}
diff --git a/src/compiler.c b/src/compiler.c
index c29f6c7..f7e6a14 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -123,6 +123,50 @@ static int process(struct scope **parent, int public, const char *file)
return 0;
}
+#define MAP_KEY char *
+#define MAP_TYPE struct scope *
+#define MAP_CMP(a, b) strcmp((a), (b))
+#define MAP_NAME scopes
+#include "ek/map.h"
+
+static int copy_scope(struct scope *to, struct scope *from)
+{
+ /** @todo handle duplicates */
+ foreach_visible(n, from->symbols) {
+ struct ast *def = n->node;
+ if (!ast_flags(def, AST_FLAG_PUBLIC))
+ continue;
+
+ switch (def->k) {
+ case AST_PROC_DEF:
+ if (scope_add_proc(to, def))
+ return -1;
+ break;
+
+ case AST_VAR_DEF:
+ if (scope_add_var(to, def))
+ return -1;
+ break;
+
+ default: abort();
+ }
+ }
+
+ return 0;
+}
+
+/* ugly global for now */
+static struct scopes scopes;
+
+static void destroy_scopes()
+{
+ foreach(scopes, n, &scopes) {
+ free(n->key);
+ }
+
+ scopes_destroy(&scopes);
+}
+
int process_file(struct scope **scope, int public, const char *file)
{
int res = -1;
@@ -141,7 +185,7 @@ int process_file(struct scope **scope, int public, const char *file)
if (!dir)
goto out;
- /* TODO: iterate through include paths */
+ /* TODO: iterate through include paths? */
const char *cwd = ek_cwdname();
res_add(r, (void *)cwd);
if (!cwd)
@@ -153,8 +197,20 @@ int process_file(struct scope **scope, int public, const char *file)
goto out;
}
- if (process(scope, public, base))
- goto out;
+ char *real = realpath(base, NULL);
+ assert(real);
+
+ struct scope **exists = scopes_find(&scopes, real);
+ if (exists) {
+ if (copy_scope(*scope, *exists))
+ goto out;
+
+ } else {
+ if (process(scope, public, base))
+ goto out;
+
+ scopes_insert(&scopes, real, *scope);
+ }
if (chdir(cwd)) {
error("couldn't change back to directory %s: %s\n", cwd,
@@ -170,11 +226,14 @@ out:
}
int compile(const char *input) {
+ scopes = scopes_create();
+
int ret = -1;
struct scope *root = NULL;
if (process_file(&root, 0, input)) {
destroy_scope(root);
destroy_allocs();
+ destroy_scopes();
error("compilation of %s stopped due to errors", input);
return ret;
}
@@ -182,11 +241,13 @@ int compile(const char *input) {
if ((ret = lower(root))) {
destroy_scope(root);
destroy_allocs();
+ destroy_scopes();
error("compilation of %s stopped due to errors", input);
return ret;
}
destroy_scope(root);
destroy_allocs();
+ destroy_scopes();
return 0;
}
diff --git a/src/lower.c b/src/lower.c
index e6c147f..8aefd68 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -196,6 +196,11 @@ typedef int (*visit_struct_t)(struct lower_state *s, struct ast *n, size_t o,
static ssize_t visit_struct(struct lower_state *s, struct ast *def, size_t base,
visit_struct_t cb, void *data)
{
+ /* I believe we're only interested in the variables, so find them at the
+ * root of the chain */
+ if (def->chain)
+ return visit_struct(s, def->chain, base, cb, data);
+
size_t offset = (size_t)base;
foreach_node(n, struct_body(def)) {
if (n->k != AST_VAR_DEF)
@@ -879,12 +884,49 @@ static int lower_call(struct lower_state *s, struct ast *c,
assert(c->k == AST_CALL);
struct retval call = retval_create();
+ if (ast_flags(c, AST_FLAG_UFCS_SIMPLE)
+ || ast_flags(c, AST_FLAG_UFCS_REF)
+ || ast_flags(c, AST_FLAG_UFCS_TRIVIAL)) {
+ struct ast *dot = call_expr(c);
+ assert(dot && dot->k == AST_DOT);
+
+ struct ast *expr = dot_expr(dot);
+
+ char *id = strdup(dot_id(dot));
+ assert(id);
+
+ struct ast *fetch = gen_fetch(id, clone_type(expr->t),
+ dot->loc);
+ assert(fetch);
+
+ fetch->t = clone_type(dot->t);
+ call_expr(c) = fetch;
+
+ if (!ast_flags(c, AST_FLAG_UFCS_TRIVIAL)) {
+ struct ast *arg = expr;
+ if (ast_flags(c, AST_FLAG_UFCS_REF)) {
+ arg = gen_unop(AST_REF, expr, dot->loc);
+ arg->t = clone_type(expr->t);
+ /** @todo should simplify refderef here */
+ }
+
+ /* prepend new arg to list */
+ arg->n = call_args(c);
+ call_args(c) = arg;
+ }
+ }
+
if (lower_expr(s, call_expr(c), &call)) {
retval_destroy(&call);
return -1;
}
- struct type *rtype = callable_rtype((call_expr(c))->t);
+ struct ast *expr = call_expr(c);
+ struct type *callable = expr->t;
+ if (callable->k == TYPE_PTR)
+ callable = ptr_base(callable);
+
+ struct type *rtype = callable_rtype(callable);
char *rbuf = NULL;
if (rtype->k == TYPE_STRUCT) {
rbuf = build_str("rbuf_%zd", s->uniq++);
diff --git a/src/parser.y b/src/parser.y
index 3808807..18de0e1 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -643,13 +643,15 @@ opt_sign_decls
type
: ID { $$ = tgen_id($1, src_loc(@$)); }
- | "^" "(" opt_sign_decls "=>" opt_type ")" {
+ | "*" "(" opt_sign_decls "=>" opt_type ")" {
/* still not entirely sold on this signature, but it's not terrible I
* guess */
$$ = tgen_callable($[opt_sign_decls], $[opt_type], src_loc(@$));
+ $$ = tgen_ptr($$, src_loc(@$));
}
- | "^" "(" opt_sign_decls ")" {
+ | "*" "(" opt_sign_decls ")" {
$$ = tgen_callable($[opt_sign_decls], NULL, src_loc(@$));
+ $$ = tgen_ptr($$, src_loc(@$));
}
| "*" type {
$$ = tgen_ptr($2, src_loc(@$));
diff --git a/src/scope.c b/src/scope.c
index 6687d98..8ffe2f9 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -297,7 +297,7 @@ int scope_add_proc(struct scope *scope, struct ast *proc)
{
assert(proc->k == AST_PROC_DEF);
struct ast *exists = file_scope_find_symbol(scope, proc_id(proc));
- if (exists) {
+ if (exists && proc_body(exists) == proc_body(proc)) {
semantic_error(proc->scope->fctx, proc, "proc redefined");
semantic_info(exists->scope->fctx, exists, "previously here");
return -1;
@@ -361,44 +361,14 @@ static struct expanded *scope_find_expanded(struct expanded *e, struct ast *def,
return NULL;
}
-static void insert_expd_chain(struct scope *scope, struct ast *def,
- struct type *types, struct ast *expd)
-{
- struct expanded *e = scope_find_expanded(scope->expanded, def, types);
- assert(e);
-
- struct ast *n = e->expd;
- assert(n);
-
- if (ast_flags(n, AST_FLAG_PUBLIC)
- || !ast_flags(expd, AST_FLAG_PUBLIC)) {
- expd->chain = e->expd;
- e->expd = expd;
- /* types should be identical, we checked that earlier */
- return;
- }
-
- /* find first public continuation in chain and insert just before it */
- struct ast *next = n->chain;
- while (next->k == AST_STRUCT_CONT_DEF &&
- !ast_flags(next, AST_FLAG_PUBLIC)) {
- n = next;
- next = n->chain;
- }
-
- n->chain = expd;
- expd->chain = next;
-}
-
int scope_add_expd_chain(struct scope *scope, struct ast *def,
struct type *types, struct ast *expd)
{
- assert(def->k == AST_STRUCT_DEF);
+ assert(def->k == AST_STRUCT_CONT_DEF);
assert(expd->k == AST_STRUCT_CONT_DEF);
- assert(file_scope_find_expd_struct(scope, def, types) != NULL);
-
- insert_expd_chain(scope, def, types, expd);
+ assert(file_scope_find_expd_struct(scope, def, types) == NULL);
+ create_expanded(scope, def, types, expd);
if (scope_add_recurse(scope, expd))
return scope_add_expd_chain(scope->parent, def, types, expd);
@@ -537,7 +507,7 @@ struct ast *file_scope_find_var(struct scope *scope, char *id)
struct ast *scope_find_expd_struct(struct scope *scope, struct ast *def,
struct type *types)
{
- assert(def->k == AST_STRUCT_DEF);
+ assert(def->k == AST_STRUCT_DEF || def->k == AST_STRUCT_CONT_DEF);
struct expanded *expd = scope_find_expanded(scope->expanded, def,
types);
if (!expd)