aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c212
-rw-r--r--src/ast.c96
-rw-r--r--src/debug.c22
-rw-r--r--src/parser.y4
-rw-r--r--src/scope.c43
5 files changed, 323 insertions, 54 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 4d1d449..b25968f 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -337,6 +337,11 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
break;
}
+ case AST_UNION: {
+ ret |= scope_add_type(scope, node);
+ break;
+ }
+
case AST_ENUM: {
ret |= scope_add_type(scope, node);
break;
@@ -1251,6 +1256,11 @@ static int actualize_type(struct act_state *state,
EXIT_ACT(-1);
}
+ /* this could be more clear, maybe add into the parser some kind
+ * of meta class for templated types? */
+ if (exists->node_type == AST_UNION)
+ type->_type.kind = AST_TYPE_UNION;
+
/* nothing to do, except maybe check that types are actually
* identical? */
if (exists->node_type == AST_TYPE)
@@ -1300,6 +1310,9 @@ static int actualize_type(struct act_state *state,
type->_type.unio.impls = NULL;
}
+ if (ast_flags(exists, AST_FLAG_GENERIC))
+ ast_set_flags(type, AST_FLAG_GENERIC);
+
break;
}
@@ -1344,11 +1357,24 @@ static int actualize_type(struct act_state *state,
break;
}
+ case AST_TYPE_UNION:
case AST_TYPE_STRUCT: {
- struct ast_node *id = type->_type.struc.id;
+ assert(ast_flags(type, AST_FLAG_ACTUAL));
+ break;
+ }
+
+ case AST_TYPE_GENERIC: {
+ struct ast_node *id = type->_type.generic.id;
struct ast_node *exists = file_scope_resolve_type(scope, id);
- if (!exists || exists->node_type != AST_STRUCT) {
- semantic_error(scope->fctx, type, "no such struct");
+ if (!exists) {
+ semantic_error(scope->fctx, type, "no such type");
+ EXIT_ACT(-1);
+ }
+
+ if (exists->node_type != AST_UNION &&
+ exists->node_type != AST_STRUCT) {
+ semantic_error(scope->fctx, type,
+ "type not struct or union");
EXIT_ACT(-1);
}
@@ -1356,7 +1382,7 @@ static int actualize_type(struct act_state *state,
if (actualize(state, exists->scope, exists))
EXIT_ACT(-1);
- struct ast_node *types = type->_type.struc.impls;
+ struct ast_node *types = type->_type.generic.args;
if (actualize(state, scope, types))
EXIT_ACT(-1);
@@ -1377,14 +1403,17 @@ static int actualize_type(struct act_state *state,
types = types->next;
}
- break;
- }
+ if (exists->node_type == AST_UNION)
+ type->_type.kind = AST_TYPE_UNION;
+ else
+ type->_type.kind = AST_TYPE_STRUCT;
- case AST_TYPE_MEMBER: {
- /* TODO */
break;
}
+ default:
+ semantic_error(scope->fctx, type, "unimplemented type");
+ EXIT_ACT(-1);
}
ast_set_flags(type, AST_FLAG_ACTUAL);
@@ -1494,16 +1523,16 @@ static size_t member_count(struct ast_node *exists)
return ast_list_len(body);
}
-static struct ast_node *lookup_struct_member_idx(struct ast_node *struc,
- struct ast_node *find,
- size_t *idx)
+static struct ast_node *lookup_member_idx(struct ast_node *body,
+ struct ast_node *find,
+ size_t *idx)
{
/* micro-optimisation, likely way premature but speeds up selection
* between lookup_struct_member_idx and *_name by a tiny amount */
(void)(find);
-
+ assert(idx);
size_t i = *idx;
- struct ast_node *m = struc->_struct.body;
+ struct ast_node *m = body;
while (i != 0 && m) {
m = m->next;
i--;
@@ -1512,12 +1541,13 @@ static struct ast_node *lookup_struct_member_idx(struct ast_node *struc,
return m;
}
-static struct ast_node *lookup_struct_member_name(struct ast_node *struc,
- struct ast_node *find,
- size_t *idx)
+static struct ast_node *lookup_member_name(struct ast_node *body,
+ struct ast_node *find,
+ size_t *idx)
{
+ assert(find->node_type == AST_ID);
size_t i = 0;
- struct ast_node *m = struc->_struct.body;
+ struct ast_node *m = body;
while (m) {
assert(m->node_type == AST_VAR);
if (identical_ast_nodes(0, find, m->_var.id))
@@ -1526,7 +1556,9 @@ static struct ast_node *lookup_struct_member_name(struct ast_node *struc,
i++;
}
- *idx = i;
+ if (idx)
+ *idx = i;
+
return m;
}
@@ -1534,9 +1566,19 @@ static struct ast_node *lookup_struct_member(struct ast_node *struc,
struct ast_node *find, size_t *idx)
{
if (find)
- return lookup_struct_member_name(struc, find, idx);
+ return lookup_member_name(struc->_struct.body, find, idx);
+
+ return lookup_member_idx(struc->_struct.body, find, idx);
+}
+
+static struct ast_node *lookup_union_member(struct ast_node *unio,
+ struct ast_node *find)
+{
+ if (find)
+ return lookup_member_name(unio->_union.body, find, NULL);
- return lookup_struct_member_idx(struc, find, idx);
+ size_t idx = 0;
+ return lookup_member_idx(unio->_union.body, find, &idx);
}
static struct ast_node *lookup_enum_member(struct ast_node *enu,
@@ -1555,11 +1597,53 @@ static struct ast_node *lookup_enum_member(struct ast_node *enu,
return m;
}
+static int init_union(struct act_state *state, struct scope *scope,
+ struct ast_node *exists, struct ast_node *init)
+{
+ struct ast_node *arg = init->_init.body;
+ if (arg->next) {
+ semantic_error(scope->fctx, arg->next,
+ "multiple arguments in union initialization not allowed");
+ return -1;
+ }
+
+ if (actualize(state, scope, arg))
+ return -1;
+
+ struct ast_node *member = NULL;
+ if (ast_flags(arg, AST_FLAG_MEMBER)) {
+ member = lookup_union_member(exists, arg->_var.id);
+ }
+ else {
+ /* pick first element in body */
+ member = exists->_union.body;
+ }
+
+ if (!member) {
+ char *sstr = type_str(exists->type);
+ semantic_error(scope->fctx, arg,
+ "no such member in %s",
+ sstr);
+ free(sstr);
+ return -1;
+ }
+
+ if (!implements(0, scope, arg->type, member->type)) {
+ char *mstr = type_str(member->type);
+ char *astr = type_str(arg->type);
+ semantic_error(scope->fctx, arg, "%s does not implement %s",
+ astr, mstr);
+ free(mstr);
+ free(astr);
+ return -1;
+ }
+
+ return 0;
+}
+
static int init_struct(struct act_state *state, struct scope *scope,
struct ast_node *exists, struct ast_node *init)
{
- assert(ast_flags(exists, AST_FLAG_ACTUAL));
-
size_t i = 0;
size_t mcount = member_count(exists);
@@ -1653,24 +1737,48 @@ struct ast_node *actual_type(struct ast_node *type)
return type;
}
-static int actualize_struct_init(struct act_state *state,
- struct scope *scope, struct ast_node *init,
- struct ast_node *struct_type)
+static int actualize_struct_init_cast(struct act_state *state,
+ struct scope *scope,
+ struct ast_node *init,
+ struct ast_node *actual)
{
- struct ast_node *actual = actual_type(struct_type);
- if (actual->_type.kind != AST_TYPE_STRUCT) {
- semantic_error(scope->fctx, struct_type,
- "type is not a structure");
- return -1;
- }
-
struct ast_node *id = actual->_type.struc.id;
struct ast_node *exists = file_scope_resolve_type(scope, id);
assert(exists);
+ assert(ast_flags(exists, AST_FLAG_ACTUAL));
return init_struct(state, scope, exists, init);
}
+static int actualize_union_init_cast(struct act_state *state,
+ struct scope *scope,
+ struct ast_node *init,
+ struct ast_node *actual)
+{
+ struct ast_node *id = actual->_type.unio.id;
+ struct ast_node *exists = file_scope_resolve_type(scope, id);
+ assert(exists);
+ assert(ast_flags(exists, AST_FLAG_ACTUAL));
+
+ return init_union(state, scope, exists, init);
+}
+
+static int actualize_init_cast(struct act_state *state,
+ struct scope *scope, struct ast_node *init,
+ struct ast_node *type)
+{
+ struct ast_node *actual = actual_type(type);
+ if (actual->_type.kind == AST_TYPE_STRUCT)
+ return actualize_struct_init_cast(state, scope, init, actual);
+ if (actual->_type.kind == AST_TYPE_UNION)
+ return actualize_union_init_cast(state, scope, init, actual);
+
+ semantic_error(scope->fctx, type,
+ "type is not a struct or union");
+ return -1;
+
+}
+
static int proc_pointer(struct ast_node *type)
{
if (type->_type.kind != AST_TYPE_POINTER)
@@ -1698,6 +1806,7 @@ static int proc_choice(struct ast_node *expr, struct ast_node *type)
static int match_proc(struct act_state *state, struct scope *scope,
struct ast_node *cast)
{
+ (void)(state);
semantic_error(scope->fctx, cast,
"procedure signature casts not yet implemented");
return -1;
@@ -1723,7 +1832,7 @@ static int actualize_cast(struct act_state *state,
if (expr->node_type == AST_INIT) {
cast->type = type;
- return actualize_struct_init(state, scope, expr, type);
+ return actualize_init_cast(state, scope, expr, type);
}
if (types_match(expr->type, type)) {
@@ -2068,6 +2177,8 @@ static int actualize_struct(struct act_state *state,
return -1;
scope_add_scope(node->scope, struct_scope);
+ if (generics)
+ ast_set_flags(node, AST_FLAG_GENERIC);
/* TODO: some IDs should be handles as just placeholders, I think? */
if (actualize(state, struct_scope, generics))
@@ -2086,6 +2197,36 @@ static int actualize_struct(struct act_state *state,
return 0;
}
+static int actualize_union(struct act_state *state,
+ struct scope *scope, struct ast_node *node)
+{
+ assert(node->node_type == AST_UNION);
+ ast_set_flags(node, AST_FLAG_INIT);
+ struct ast_node *generics = node->_union.generics;
+ struct scope *union_scope = create_scope();
+ if (!union_scope)
+ return -1;
+
+ scope_add_scope(node->scope, union_scope);
+ if (generics)
+ ast_set_flags(node, AST_FLAG_GENERIC);
+
+ if (actualize(state, union_scope, generics))
+ return -1;
+
+ struct ast_node *body = node->_union.body;
+ if (actualize(state, union_scope, body))
+ return -1;
+
+ /* cloning slightly odd, but I guess it's fine? */
+ struct ast_node *clone_id = clone_ast_node(node->_union.id);
+ node->type = gen_type(AST_TYPE_UNION, clone_id, NULL, NULL);
+ scope_add_scratch(scope, node->type);
+
+ ast_set_flags(node, AST_FLAG_ACTUAL);
+ return 0;
+}
+
/* could maybe be renamed, but essentially dot in copper works as either
* -> or . in C, so allow structures or templates and single level pointers to
* structures or templates. */
@@ -2165,7 +2306,7 @@ static int actualize_assign(struct act_state *state, struct scope *scope,
if (from->node_type == AST_INIT) {
node->type = to->type;
- return actualize_struct_init(state, scope, from, to->type);
+ return actualize_init_cast(state, scope, from, to->type);
}
if (!types_match(to->type, from->type)) {
@@ -2298,6 +2439,7 @@ static int actualize(struct act_state *state, struct scope *scope,
case AST_UNOP: ret |= actualize_unop(state, scope, node); break;
case AST_AS: ret |= actualize_as(state, scope, node); break;
case AST_STRUCT: ret |= actualize_struct(state, scope, node); break;
+ case AST_UNION: ret |= actualize_union(state, scope, node); break;
case AST_DOT: ret |= actualize_dot(state, scope, node); break;
case AST_INIT: ret |= actualize_init(state, scope, node); break;
case AST_ASSIGN: ret |= actualize_assign(state, scope, node); break;
@@ -2378,6 +2520,8 @@ void replace_type(struct ast_node *type, struct ast_node *from,
case AST_TYPE_TYPEOF:
destroy_ast_node(type->_type.typeo.expr);
break;
+
+ default:
}
*type = *clone;
free(clone);
diff --git a/src/ast.c b/src/ast.c
index 9be3f89..b8b52a3 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -423,6 +423,12 @@ struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id,
n->node_type = AST_TYPE;
n->_type.kind = kind;
switch (kind) {
+ case AST_TYPE_GENERIC:
+ n->_type.generic.id = id;
+ n->_type.generic.args = expr;
+ n->loc = id->loc;
+ break;
+
case AST_TYPE_MEMBER:
n->_type.member.id = id;
n->_type.member.expr = expr;
@@ -504,6 +510,16 @@ void destroy_type(struct ast_node *type)
{
assert(type->node_type == AST_TYPE);
switch (type->_type.kind) {
+ case AST_TYPE_GENERIC:
+ destroy_ast_node(type->_type.generic.id);
+ DESTROY_LIST(type->_type.generic.args);
+ break;
+
+ case AST_TYPE_MEMBER:
+ destroy_ast_node(type->_type.member.id);
+ destroy_ast_node(type->_type.member.expr);
+ break;
+
case AST_TYPE_ALIAS:
break;
@@ -1289,6 +1305,12 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_flags(node);
switch (node->_type.kind) {
+ case AST_TYPE_GENERIC:
+ printf(" GENERIC\n");
+ dump_ast(depth + 1, node->_type.generic.id);
+ dump_ast(depth + 1, node->_type.generic.args);
+ break;
+
case AST_TYPE_MEMBER:
printf(" MEMBER\n");
dump_ast(depth + 1, node->_type.member.id);
@@ -1677,14 +1699,24 @@ struct ast_node *clone_ast_node(struct ast_node *node)
/* oh, if a node has a ->type it probably isn't cloned
* correctly... */
switch (node->_type.kind) {
+ case AST_TYPE_GENERIC:
+ new = gen_type(AST_TYPE_GENERIC,
+ clone_ast_node(node->_type.generic.id),
+ clone_ast_node(node->_type.generic.args),
+ NULL);
+ break;
+
case AST_TYPE_MEMBER:
- new = gen_type(AST_TYPE_MEMBER, node->_type.member.id,
- node->_type.member.expr,
+ new = gen_type(AST_TYPE_MEMBER,
+ clone_ast_node(node->_type.member.id),
+ clone_ast_node(node->_type.member.expr),
NULL);
break;
case AST_TYPE_ALIAS:
new = gen_type(AST_TYPE_ALIAS, NULL,
+ /* should make it more obvious what is a
+ * reference and what isn't */
node->_type.alias.alias,
node->_type.alias.actual);
break;
@@ -1692,7 +1724,7 @@ struct ast_node *clone_ast_node(struct ast_node *node)
case AST_TYPE_TEMPLATE:
new = gen_type(AST_TYPE_TEMPLATE, NULL,
node->_type.template.template,
- /* should actual be cloned? */
+ /* ditto, should actual be cloned? */
node->_type.template.actual);
break;
case AST_TYPE_ID:
@@ -1758,6 +1790,8 @@ struct ast_node *clone_ast_node(struct ast_node *node)
break;
}
+
+ assert(new);
new->_type.next = clone_ast_node(node->_type.next);
break;
@@ -2180,7 +2214,7 @@ static int identical_type_struct(int exact, struct ast_node *a,
if (!identical_ast_nodes(exact, a->_type.struc.id, b->_type.struc.id))
return 0;
- if (!identical_ast_nodes(exact, a->_type.struc.impls,
+ if (!identical_ast_nodes(1, a->_type.struc.impls,
b->_type.struc.impls))
return 0;
@@ -2193,7 +2227,7 @@ static int identical_type_union(int exact, struct ast_node *a,
if (!identical_ast_nodes(exact, a->_type.unio.id, b->_type.unio.id))
return 0;
- if (!identical_ast_nodes(exact, a->_type.unio.impls,
+ if (!identical_ast_nodes(1, a->_type.unio.impls,
b->_type.unio.impls))
return 0;
@@ -2212,6 +2246,34 @@ static int identical_type_enum(int exact, struct ast_node *a,
return 1;
}
+static int identical_type_member(int exact, struct ast_node *a,
+ struct ast_node *b)
+{
+ if (!identical_ast_nodes(exact, a->_type.member.id, b->_type.member.id))
+ return 0;
+
+ if (!identical_ast_nodes(exact, a->_type.member.expr,
+ b->_type.member.expr))
+ return 0;
+
+ return 1;
+}
+
+static int identical_type_generic(int exact, struct ast_node *a,
+ struct ast_node *b)
+{
+ if (!identical_ast_nodes(exact, a->_type.generic.id,
+ b->_type.generic.id))
+ return 0;
+
+ /* array should always be checked, so do an exact match */
+ if (!identical_ast_nodes(1, a->_type.generic.args,
+ b->_type.generic.args))
+ return 0;
+
+ return 1;
+}
+
static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
{
if (a->_type.kind != b->_type.kind)
@@ -2219,6 +2281,8 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->_type.kind) {
+ case AST_TYPE_GENERIC: ret = identical_type_generic(exact, a, b); break;
+ case AST_TYPE_MEMBER: ret = identical_type_member(exact, a, b); break;
case AST_TYPE_ENUM: ret = identical_type_enum(exact, a, b); break;
case AST_TYPE_ALIAS: ret = identical_type_alias(exact, a, b); break;
case AST_TYPE_TEMPLATE: ret = identical_type_template(exact, a, b);
@@ -2767,11 +2831,33 @@ static int call_on_type_enum(int (*call)(struct ast_node *,
return ret;
}
+static int call_on_type_member(int (*call)(struct ast_node *,
+ void *), struct ast_node *node, void *data)
+{
+ int ret = 0;
+ ret |= call(node->_type.member.id, data);
+ ret |= call(node->_type.member.expr, data);
+ return ret;
+}
+
+static int call_on_type_generic(int (*call)(struct ast_node *,
+ void *), struct ast_node *node, void *data)
+{
+ int ret = 0;
+ ret |= call(node->_type.generic.id, data);
+ ret |= call(node->_type.generic.args, data);
+ return ret;
+}
+
static int call_on_type(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
switch (node->_type.kind) {
+ case AST_TYPE_GENERIC: ret = call_on_type_generic(call, node, data);
+ break;
+ case AST_TYPE_MEMBER: ret = call_on_type_member(call, node, data);
+ break;
case AST_TYPE_ENUM: ret = call_on_type_enum(call, node, data); break;
case AST_TYPE_ALIAS: ret = call_on_type_alias(call, node, data); break;
case AST_TYPE_TEMPLATE: ret = call_on_type_template(call, node, data);
diff --git a/src/debug.c b/src/debug.c
index b929876..f850973 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -210,10 +210,32 @@ static void _type_str(FILE *fp, struct ast_node *type)
break;
}
+ case AST_TYPE_UNION: {
+ struct ast_node *unio_id = type->_type.unio.id;
+ fprintf(fp, "%s", unio_id->_id.id);
+
+ struct ast_node *impls = type->_type.unio.impls;
+ if (impls) {
+ fprintf(fp, "(");
+ while (impls) {
+ _type_str(fp, impls);
+ impls = impls->next;
+ if (impls)
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ")");
+ }
+ break;
+ }
+
case AST_TYPE_TYPEOF: {
_type_str(fp, type->_type.typeo.actual);
fprintf(fp, " (typeof)");
+ break;
}
+
+ default:
+ fprintf(fp, "NOT YET IMPLEMENTED");
}
_type_str(fp, type->_type.next);
diff --git a/src/parser.y b/src/parser.y
index 329e072..64f9ef1 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -448,7 +448,7 @@ type: id { $$ = gen_type(AST_TYPE_ID, $1, NULL, NULL); }
$$->_type.next = $2;
}
| id "(" type_list ")" {
- $$ = gen_type(AST_TYPE_STRUCT, $1, $3, NULL);
+ $$ = gen_type(AST_TYPE_GENERIC, $1, $3, NULL);
}
| "'" type {
$$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
@@ -596,6 +596,7 @@ top: ";" { $$ = gen_empty(); }
| enum { $$ = $1; }
| proc { $$ = $1; }
| struct { $$ = $1; }
+ | union { $$ = $1; }
| macro { $$ = $1; }
| "const" top_if { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); }
| import ";" { $$ = $1; }
@@ -603,6 +604,7 @@ top: ";" { $$ = gen_empty(); }
| type_template { $$ = $1; }
| "pub" enum { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
+ | "pub" union { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" proc { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" macro { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" import ";" { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
diff --git a/src/scope.c b/src/scope.c
index c2b8aab..b5f7960 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -75,6 +75,9 @@ int fully_qualified(struct ast_node *type)
assert(type->_type.kind != AST_TYPE_TEMPLATE);
if (type->_type.kind == AST_TYPE_STRUCT) {
+ if (!ast_flags(type, AST_FLAG_GENERIC))
+ return 1;
+
if (type->_type.struc.impls)
return fully_qualified(type->_type.struc.impls);
@@ -82,6 +85,9 @@ int fully_qualified(struct ast_node *type)
}
if (type->_type.kind == AST_TYPE_UNION) {
+ if (!ast_flags(type, AST_FLAG_GENERIC))
+ return 1;
+
if (type->_type.unio.impls)
return fully_qualified(type->_type.unio.impls);
@@ -91,8 +97,7 @@ int fully_qualified(struct ast_node *type)
return fully_qualified(type->_type.next);
}
-static struct param_node *find_primitive(struct scope *scope,
- struct proc_node *node,
+static struct param_node *find_primitive(struct proc_node *node,
struct ast_node *type)
{
struct param_node *param = node->primitives;
@@ -123,8 +128,7 @@ static int compare_primitives(struct ast_node *a, struct ast_node *b);
* otherwise use find_primitive() to get which primitive matches.
* (are these names inverted from their intention? I'm not sure)
*/
-static struct param_node *match_primitive(struct scope *scope,
- struct proc_node *node,
+static struct param_node *match_primitive(struct proc_node *node,
struct ast_node *type)
{
struct param_node *param = node->primitives;
@@ -265,8 +269,7 @@ static int add_next_resolve(struct scope *scope, struct ast_node *proc,
assert(params->node_type == AST_VAR);
if (primitive_type(params->type)) {
- struct param_node *match = match_primitive(scope, node,
- params->type);
+ struct param_node *match = match_primitive(node, params->type);
if (match)
return add_next_resolve(scope, proc, match->proc,
params->next);
@@ -361,7 +364,7 @@ static struct ast_node *proc_resolve(struct scope *scope,
}
/* first check if we match a primitive type */
- struct param_node *found = find_primitive(scope, node, args->type);
+ struct param_node *found = find_primitive(node, args->type);
if (found)
return proc_resolve(scope, found->proc, args->next);
@@ -508,6 +511,7 @@ void destroy_scope(struct scope *scope)
destroy_visible(scope, scope->builtins);
destroy_visible(scope, scope->enums);
+ destroy_visible(scope, scope->unions);
destroy_visible(scope, scope->structs);
destroy_visible(scope, scope->aliases);
destroy_visible(scope, scope->templates);
@@ -568,6 +572,7 @@ CREATE_VISIBLE(create_proc, procs, AST_PROC);
CREATE_VISIBLE(create_enum, enums, AST_ENUM);
CREATE_VISIBLE(create_alias, aliases, AST_ALIAS);
CREATE_VISIBLE(create_struct, structs, AST_STRUCT);
+CREATE_VISIBLE(create_union, unions, AST_UNION);
CREATE_VISIBLE(create_builtin, builtins, AST_TYPE);
CREATE_VISIBLE(create_template, templates, AST_TEMPLATE);
@@ -592,6 +597,7 @@ REFERENCE_VISIBLE(reference_proc, procs, AST_PROC);
REFERENCE_VISIBLE(reference_enum, enums, AST_ENUM);
REFERENCE_VISIBLE(reference_alias, aliases, AST_ALIAS);
+REFERENCE_VISIBLE(reference_union, unions, AST_UNION);
REFERENCE_VISIBLE(reference_struct, structs, AST_STRUCT);
REFERENCE_VISIBLE(reference_builtin, builtins, AST_TYPE);
REFERENCE_VISIBLE(reference_template, templates, AST_TEMPLATE);
@@ -620,6 +626,7 @@ FIND_VISIBLE(scope_find_enum, enums, AST_ENUM, _enum);
FIND_VISIBLE(scope_find_alias, aliases, AST_ALIAS, _alias);
FIND_VISIBLE(scope_find_builtin, builtins, AST_TYPE, _type);
FIND_VISIBLE(scope_find_struct, structs, AST_STRUCT, _struct);
+FIND_VISIBLE(scope_find_union, unions, AST_UNION, _union);
FIND_VISIBLE(scope_find_template, templates, AST_TEMPLATE, _template);
/* note that these return the first match for the ID, and as such might not be
* what should be called. */
@@ -685,6 +692,7 @@ struct visible *create_type(struct scope *scope, struct ast_node *type)
case AST_TEMPLATE: return create_template(scope, type);
case AST_ENUM: return create_enum(scope, type);
case AST_STRUCT: return create_struct(scope, type);
+ case AST_UNION: return create_union(scope, type);
default:
semantic_error(scope->fctx, type, "unknown type");
return NULL;
@@ -699,6 +707,7 @@ int reference_type(int public, struct scope *scope, struct visible *visible)
case AST_TEMPLATE: return reference_template(public, scope, visible);
case AST_ENUM: return reference_enum(public, scope, visible);
case AST_STRUCT: return reference_struct(public, scope, visible);
+ case AST_UNION: return reference_union(public, scope, visible);
default:
semantic_error(scope->fctx, visible->node, "unknown type");
return 1;
@@ -743,6 +752,10 @@ struct ast_node *scope_find_type(struct scope *scope, struct ast_node *id)
if (found)
return found;
+ found = scope_find_union(scope, id);
+ if (found)
+ return found;
+
found = scope_find_alias(scope, id);
if (found)
return found;
@@ -914,6 +927,10 @@ static int implements_var(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type,
struct ast_node *param_type, struct ast_node *var)
{
+ (void)(flags);
+ (void)(scope);
+ (void)(arg_type);
+ (void)(param_type);
assert(var->node_type == AST_VAR);
/* temp */
return 0;
@@ -1017,13 +1034,6 @@ static int implements_typeof(enum match_flags flags, struct scope *scope,
return implements(flags, scope, arg_type, param_type);
}
-static int implements_pointer(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type)
-{
- return implements(flags, scope, arg_type, param_type);
-}
-
int implements(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type, struct ast_node *param_type)
{
@@ -1169,6 +1179,7 @@ static int match_params(enum match_flags flags, struct scope *scope,
static struct ast_node *match_proc(enum match_flags flags, struct scope *scope,
struct ast_node *id, struct ast_node *args)
{
+ (void)(flags);
struct callable *cb = scope->callable;
while (cb) {
if (identical_ast_nodes(0, cb->id, id))
@@ -1548,6 +1559,10 @@ struct ast_node *scope_resolve_type(struct scope *scope, struct ast_node *type)
id = type->_struct.id;
break;
+ case AST_UNION:
+ id = type->_union.id;
+ break;
+
case AST_ENUM:
id = type->_enum.id;
break;