aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-11-07 13:09:44 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2023-11-07 13:09:44 +0200
commit8dce541c96a329e3b12f3ea3794fcc8202fbd134 (patch)
tree0b086b998c9d392242acba0a7518fa3d535b1c56 /src
parentbb560b4201d8b813ed3999250845f365ff9d6c50 (diff)
downloadek-8dce541c96a329e3b12f3ea3794fcc8202fbd134.tar.gz
ek-8dce541c96a329e3b12f3ea3794fcc8202fbd134.zip
simplift syntax somewhat
+ Explicit macro expansion + Still have to simplify AST and type stuff, probably worth rewriting or something
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c130
-rw-r--r--src/ast.c258
-rw-r--r--src/debug.c20
-rw-r--r--src/lexer.l10
-rw-r--r--src/parser.y144
-rw-r--r--src/scope.c154
6 files changed, 292 insertions, 424 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 866f438..3a381e0 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -35,7 +35,7 @@ struct act_state {
enum act_flags flags;
struct ast_node *last_var;
- struct ast_node *cur_template;
+ struct ast_node *cur_trait;
struct ast_node *cur_proc;
struct act_stack *defer_stack;
struct act_stack *goto_stack;
@@ -359,7 +359,7 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
break;
}
- case AST_TEMPLATE: {
+ case AST_TRAIT: {
ret |= scope_add_type(scope, node);
break;
}
@@ -473,13 +473,13 @@ int analyze_root(struct scope *scope, struct ast_node *tree)
return 0;
}
-int template_match(struct ast_node *a, struct ast_node *b)
+int trait_match(struct ast_node *a, struct ast_node *b)
{
- while (a && a->_type.kind == AST_TYPE_TEMPLATE)
- a = a->_type.template.actual;
+ while (a && a->_type.kind == AST_TYPE_TRAIT)
+ a = a->_type.trait.actual;
- while (b && b->_type.kind == AST_TYPE_TEMPLATE)
- b = b->_type.template.actual;
+ while (b && b->_type.kind == AST_TYPE_TRAIT)
+ b = b->_type.trait.actual;
return types_match(a, b);
}
@@ -592,10 +592,10 @@ int types_match(struct ast_node *a, struct ast_node *b)
}
/* handle special cases that should match even with different type kinds */
- if (a->_type.kind == AST_TYPE_TEMPLATE ||
- b->_type.kind == AST_TYPE_TEMPLATE) {
- /* TODO: check template type name */
- if (template_match(a, b))
+ if (a->_type.kind == AST_TYPE_TRAIT ||
+ b->_type.kind == AST_TYPE_TRAIT) {
+ /* TODO: check trait type name */
+ if (trait_match(a, b))
return 1;
return 0;
}
@@ -705,41 +705,41 @@ struct ast_node *extract_typeof(struct ast_node *type)
return extract_typeof(type->_type.next);
}
-struct ast_node *extract_template(struct ast_node *type)
+struct ast_node *extract_trait(struct ast_node *type)
{
if (!type)
return 0;
assert(type->node_type == AST_TYPE);
- if (type->_type.kind == AST_TYPE_TEMPLATE)
+ if (type->_type.kind == AST_TYPE_TRAIT)
return type;
- return extract_template(type->_type.next);
+ return extract_trait(type->_type.next);
}
-static void actualize_template_types(struct ast_node *params,
+static void actualize_trait_types(struct ast_node *params,
struct ast_node *args)
{
/* replace parameter types with argument types */
if (args)
do {
assert(params->type);
- struct ast_node *template = extract_template(
+ struct ast_node *trait = extract_trait(
params->type);
- if (template) {
+ if (trait) {
/* at this point we know that the types will
* match, otherwise match_proc and friends
* fucked up */
struct ast_node *type = params->type;
struct ast_node *base = args->type;
- while (type != template) {
+ while (type != trait) {
type = type->_type.next;
base = base->_type.next;
assert(type);
assert(base);
}
- template->_type.template.actual = base;
+ trait->_type.trait.actual = base;
}
params = params->next;
args = args->next;
@@ -799,7 +799,7 @@ static int actualize_proc_call(struct act_state *state,
struct ast_node *params = sign->_type.sign.params;
struct ast_node *args = call->_call.args;
/* fuck, analyze_proc gobbles up the return type typeof */
- actualize_template_types(params, args);
+ actualize_trait_types(params, args);
if (actualize(state, tmp, sign))
return -1;
@@ -809,7 +809,7 @@ static int actualize_proc_call(struct act_state *state,
}
/* clone procedure definition to
- * replace template types with actual types and actualize it */
+ * replace trait types with actual types and actualize it */
struct ast_node *def = clone_ast_node(proc);
if (!def) {
/* internal error */
@@ -820,7 +820,7 @@ static int actualize_proc_call(struct act_state *state,
struct ast_node *sign = def->_proc.sign;
struct ast_node *params = sign->_type.sign.params;
struct ast_node *args = call->_call.args;
- actualize_template_types(params, args);
+ actualize_trait_types(params, args);
if (actualize(state, def->scope, def))
return -1;
@@ -974,7 +974,7 @@ static int undefined_gotos(struct act_state *state, struct scope *scope)
static int actualize_proc(struct act_state *state,
struct scope *scope, struct ast_node *proc)
{
- /* actualize_proc is called on template procs as well, but I believe
+ /* actualize_proc is called on trait procs as well, but I believe
* that's fine? */
assert(proc && proc->node_type == AST_PROC);
int ret = 0;
@@ -1084,8 +1084,8 @@ static int actualize_binop(struct act_state *state,
return -1;
}
- /* TODO: also check template types, just because two templates collapse
- * to the same actual type doesn't mean that the two template types
+ /* TODO: also check trait types, just because two traits collapse
+ * to the same actual type doesn't mean that the two trait types
* should be allowed to operate on eachother */
/* types are the same, so the type of this expression is whichever */
@@ -1213,11 +1213,11 @@ static int actualize_var(struct act_state *state,
#define ENTER_ACT() \
enum act_flags old_flags = state->flags; \
- struct ast_node *old_template = state->cur_template;
+ struct ast_node *old_trait = state->cur_trait;
#define EXIT_ACT(r) \
do { \
- state->cur_template = old_template; \
+ state->cur_trait = old_trait; \
state->flags = old_flags; \
return r; \
} while (0);
@@ -1264,7 +1264,7 @@ static int actualize_type(struct act_state *state,
}
/* this could be more clear, maybe add into the parser some kind
- * of meta class for templated types? */
+ * of meta class for traitd types? */
if (exists->node_type == AST_UNION)
type->_type.kind = AST_TYPE_UNION;
@@ -1274,12 +1274,12 @@ static int actualize_type(struct act_state *state,
break;
assert(exists->node_type == AST_ALIAS
- || exists->node_type == AST_TEMPLATE
+ || exists->node_type == AST_TRAIT
|| exists->node_type == AST_STRUCT
|| exists->node_type == AST_ENUM
|| exists->node_type == AST_UNION);
/* actualize whatever type we have on demand, either alias or
- * template */
+ * trait */
if (!ast_flags(exists, AST_FLAG_ACTUAL))
if (actualize(state, exists->scope, exists))
EXIT_ACT(-1);
@@ -1292,11 +1292,11 @@ static int actualize_type(struct act_state *state,
type->_type.alias.alias = exists;
type->_type.alias.actual = exists->_alias.type;
}
- else if (exists->node_type == AST_TEMPLATE) {
- type->_type.kind = AST_TYPE_TEMPLATE;
- type->_type.template.template = exists;
+ else if (exists->node_type == AST_TRAIT) {
+ type->_type.kind = AST_TYPE_TRAIT;
+ type->_type.trait.trait = exists;
/* this should be populated later */
- type->_type.template.actual = NULL;
+ type->_type.trait.actual = NULL;
}
else if (exists->node_type == AST_STRUCT) {
/* I think, will still have to TODO: check */
@@ -1396,7 +1396,7 @@ static int actualize_type(struct act_state *state,
while (types) {
if (!primitive_type(types)) {
semantic_error(scope->fctx, types,
- "only primitive types allowed in template initialization");
+ "only primitive types allowed in trait initialization");
EXIT_ACT(-1);
}
@@ -1727,9 +1727,9 @@ struct ast_node *actual_type(struct ast_node *type)
return type;
}
- if (type->_type.kind == AST_TYPE_TEMPLATE) {
- if (type->_type.template.actual)
- return actual_type(type->_type.template.actual);
+ if (type->_type.kind == AST_TYPE_TRAIT) {
+ if (type->_type.trait.actual)
+ return actual_type(type->_type.trait.actual);
return type;
}
@@ -1921,33 +1921,33 @@ static int actualize_alias(struct act_state *state, struct scope *scope,
return 0;
}
-static int actualize_template(struct act_state *state, struct scope *scope,
- struct ast_node *template)
+static int actualize_trait(struct act_state *state, struct scope *scope,
+ struct ast_node *trait)
{
- assert(template->node_type == AST_TEMPLATE);
- ast_set_flags(template, AST_FLAG_ACTUAL);
+ assert(trait->node_type == AST_TRAIT);
+ ast_set_flags(trait, AST_FLAG_ACTUAL);
ENTER_ACT();
- state->cur_template = template;
+ state->cur_trait = trait;
/* will still have to figure out how I want to inform the actualizer
* that a some_type in a some_type just means whichever type we're
* testing for */
act_set_flags(state, ACT_ONLY_TYPES);
- if (actualize(state, template->scope, template->_template.body)) {
- semantic_error(scope->fctx, template,
- "failed actualizing template");
+ if (actualize(state, trait->scope, trait->_trait.body)) {
+ semantic_error(scope->fctx, trait,
+ "failed actualizing trait");
EXIT_ACT(-1);
}
- /* TODO: check that all procs in the template have something to do with
+ /* TODO: check that all procs in the trait have something to do with
* the type, either as an argument or as a return type or something */
- /* TODO: implement supertemplates, i.e. adding some previous template to
- * this template */
+ /* TODO: implement supertraits, i.e. adding some previous trait to
+ * this trait */
- /* TODO: make sure that the template itself doesn't have duplicates */
+ /* TODO: make sure that the trait itself doesn't have duplicates */
- template->type = template;
+ trait->type = trait;
EXIT_ACT(0);
}
@@ -2235,8 +2235,8 @@ static int actualize_union(struct act_state *state,
}
/* 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. */
+ * -> or . in C, so allow structures or traits and single level pointers to
+ * structures or traits. */
static int has_members(struct ast_node *type)
{
if (type->_type.kind == AST_TYPE_ALIAS)
@@ -2249,7 +2249,7 @@ static int has_members(struct ast_node *type)
if (type->_type.kind == AST_TYPE_STRUCT)
return 1;
- if (type->_type.kind == AST_TYPE_TEMPLATE)
+ if (type->_type.kind == AST_TYPE_TRAIT)
return 1;
return 0;
@@ -2281,7 +2281,7 @@ static int actualize_dot(struct act_state *state,
}
/* TODO: actually look through stuff */
- /* TODO: figure out how to match templated structures to actual */
+ /* TODO: figure out how to match traitd structures to actual */
return 0;
}
@@ -2427,7 +2427,7 @@ static int actualize(struct act_state *state, struct scope *scope,
ret |= actualize_proc(state, scope, node);
break;
- case AST_TEMPLATE: ret |= actualize_template(state, scope, node); break;
+ case AST_TRAIT: ret |= actualize_trait(state, scope, node); break;
case AST_ALIAS: ret |= actualize_alias(state, scope, node); break;
case AST_MACRO: ret |= actualize_macro(state, scope, node); break;
case AST_CALL: ret |= actualize_call(state, scope, node); break;
@@ -2541,7 +2541,7 @@ void replace_type(struct ast_node *type, struct ast_node *from,
void replace_param_types(struct ast_node *param, struct ast_node *param_type,
struct ast_node *arg_type)
{
- if (arg_type->_type.kind == AST_TYPE_TEMPLATE) {
+ if (arg_type->_type.kind == AST_TYPE_TRAIT) {
replace_param_types(param, param_type, arg_type);
return;
}
@@ -2552,33 +2552,33 @@ void replace_param_types(struct ast_node *param, struct ast_node *param_type,
}
}
-void init_template_type(struct ast_node *type, struct ast_node *param_type,
+void init_trait_type(struct ast_node *type, struct ast_node *param_type,
struct ast_node *arg_type)
{
if (!types_match(type, param_type))
return;
- struct ast_node *template = extract_template(type);
- if (template) {
+ struct ast_node *trait = extract_trait(type);
+ if (trait) {
/* TODO: this shares a fair bit of similarities with
- * actualize_template_types, could probably create a common
+ * actualize_trait_types, could probably create a common
* backend? */
- while (type != template) {
+ while (type != trait) {
type = param_type->_type.next;
arg_type = arg_type->_type.next;
assert(type);
assert(arg_type);
}
- template->_type.template.actual = arg_type;
+ trait->_type.trait.actual = arg_type;
}
}
-void init_template_types(struct ast_node *params, struct ast_node *param_type,
+void init_trait_types(struct ast_node *params, struct ast_node *param_type,
struct ast_node *arg_type)
{
while (params) {
- init_template_type(params->type, param_type, arg_type);
+ init_trait_type(params->type, param_type, arg_type);
params = params->next;
}
}
diff --git a/src/ast.c b/src/ast.c
index 3ddf7c4..999af4f 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -62,6 +62,24 @@ static struct src_loc loc_span(struct ast_node *left, struct ast_node *right)
return loc;
}
+struct ast_node *gen_macro_expansion(struct ast_node *id, struct ast_node *args)
+{
+ ALLOC_NODE(n, "macro_expansion");
+ n->node_type = AST_MACRO_EXPANSION;
+ n->_macro_expansion.id = id;
+ n->_macro_expansion.args = args;
+ n->loc = id->loc;
+ return n;
+}
+
+void destroy_macro_expansion(struct ast_node *macro_expansion)
+{
+ assert(macro_expansion->node_type == AST_MACRO_EXPANSION);
+ destroy_ast_node(macro_expansion->_macro_expansion.id);
+ destroy_ast_node(macro_expansion->_macro_expansion.args);
+ free(macro_expansion);
+}
+
struct ast_node *gen_binop(enum ast_binops op,
struct ast_node *left, struct ast_node *right)
{
@@ -448,9 +466,9 @@ struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id,
n->loc = expr->loc;
break;
- case AST_TYPE_TEMPLATE:
- n->_type.template.template = expr;
- n->_type.template.actual = ret;
+ case AST_TYPE_TRAIT:
+ n->_type.trait.trait = expr;
+ n->_type.trait.actual = ret;
n->loc = expr->loc;
break;
@@ -503,12 +521,6 @@ struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id,
n->_type.sign.ret = ret;
n->loc = loc_span(expr, ret);
break;
-
- case AST_TYPE_LAMBDA:
- n->_type.lambda.params = expr;
- n->_type.lambda.ret = ret;
- n->loc = loc_span(expr, ret);
- break;
}
return n;
@@ -531,7 +543,7 @@ void destroy_type(struct ast_node *type)
case AST_TYPE_ALIAS:
break;
- case AST_TYPE_TEMPLATE:
+ case AST_TYPE_TRAIT:
break;
case AST_TYPE_ID:
@@ -554,11 +566,6 @@ void destroy_type(struct ast_node *type)
destroy_ast_node(type->_type.proc.ret);
break;
- case AST_TYPE_LAMBDA:
- DESTROY_LIST(type->_type.lambda.params);
- destroy_ast_node(type->_type.lambda.ret);
- break;
-
case AST_TYPE_STRUCT:
destroy_ast_node(type->_type.struc.id);
DESTROY_LIST(type->_type.struc.impls);
@@ -675,27 +682,6 @@ void destroy_var(struct ast_node *var)
free(var);
}
-struct ast_node *gen_lambda(struct ast_node *captures,
- struct ast_node *type, struct ast_node *body)
-{
- ALLOC_NODE(n, "lambda");
- n->node_type = AST_LAMBDA;
- n->_lambda.captures = captures;
- n->_lambda.sign = type;
- n->_lambda.body = body;
- n->loc = captures->loc;
- return n;
-}
-
-void destroy_lambda(struct ast_node *lambda)
-{
- assert(lambda->node_type == AST_LAMBDA);
- destroy_ast_node(lambda->_lambda.sign);
- DESTROY_LIST(lambda->_lambda.captures);
- DESTROY_LIST(lambda->_lambda.body);
- free(lambda);
-}
-
struct ast_node *gen_proc(struct ast_node *id, struct ast_node *sign,
struct ast_node *body)
{
@@ -841,29 +827,29 @@ void destroy_alias(struct ast_node *alias)
free(alias);
}
-struct ast_node *gen_template(struct ast_node *id, struct ast_node *body)
+struct ast_node *gen_trait(struct ast_node *id, struct ast_node *body)
{
- ALLOC_NODE(n, "template");
- n->node_type = AST_TEMPLATE;
- n->_template.id = id;
- n->_template.body = body;
+ ALLOC_NODE(n, "trait");
+ n->node_type = AST_TRAIT;
+ n->_trait.id = id;
+ n->_trait.body = body;
n->loc = id->loc;
return n;
}
-void destroy_template(struct ast_node *template)
+void destroy_trait(struct ast_node *trait)
{
- assert(template->node_type == AST_TEMPLATE);
- destroy_ast_node(template->_template.id);
- DESTROY_LIST(template->_template.body);
+ assert(trait->node_type == AST_TRAIT);
+ destroy_ast_node(trait->_trait.id);
+ DESTROY_LIST(trait->_trait.body);
- struct template_implemented *prev = template->_template.impl_by, *cur;
+ struct trait_implemented *prev = trait->_trait.impl_by, *cur;
if (prev)
do {
cur = prev->next;
free(prev);
} while ((prev = cur));
- free(template);
+ free(trait);
}
struct ast_node *gen_import(const char *file)
@@ -945,11 +931,11 @@ void destroy_ast_node(struct ast_node *node)
case AST_CALL: destroy_call(node); break;
case AST_CAST: destroy_cast(node); break;
case AST_MACRO: destroy_macro(node); break;
+ case AST_MACRO_EXPANSION: destroy_macro_expansion(node); break;
case AST_PROC: destroy_proc(node); break;
case AST_GOTO: destroy_goto(node); break;
case AST_LABEL: destroy_label(node); break;
case AST_VAR: destroy_var(node); break;
- case AST_LAMBDA: destroy_lambda(node); break;
case AST_IF: destroy_if(node); break;
case AST_FOR: destroy_for(node); break;
case AST_WHILE: destroy_while(node); break;
@@ -967,7 +953,7 @@ void destroy_ast_node(struct ast_node *node)
case AST_CASE: destroy_case(node); break;
case AST_CONST: destroy_const(node); break;
case AST_ALIAS: destroy_alias(node); break;
- case AST_TEMPLATE: destroy_template(node); break;
+ case AST_TRAIT: destroy_trait(node); break;
case AST_ID: destroy_id(node); break;
case AST_AS: destroy_as(node); break;
case AST_EMPTY: destroy_empty(node); break;
@@ -1247,6 +1233,17 @@ static void __dump_ast(int depth, struct ast_node *node)
dump(depth, "}\n");
break;
+ case AST_MACRO_EXPANSION:
+ dump(depth, "{MACRO_EXPANSION:");
+ dump_flags(node);
+ putchar('\n');
+
+ dump_ast(depth + 1, node->_macro_expansion.id);
+ dump_ast(depth + 1, node->_macro_expansion.args);
+
+ dump(depth, "}\n");
+ break;
+
case AST_PROC:
dump(depth, "{PROC:");
dump_flags(node);
@@ -1331,11 +1328,11 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_ast(depth + 1, node->_type.alias.actual);
break;
- case AST_TYPE_TEMPLATE:
- printf(" TEMPLATE\n");
+ case AST_TYPE_TRAIT:
+ printf(" TRAIT\n");
dump_ast(depth + 1,
- node->_type.template.template->_template.id);
- dump_ast(depth + 1, node->_type.template.actual);
+ node->_type.trait.trait->_trait.id);
+ dump_ast(depth + 1, node->_type.trait.actual);
break;
case AST_TYPE_ID:
@@ -1364,12 +1361,6 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_ast(depth + 1, node->_type.proc.ret);
break;
- case AST_TYPE_LAMBDA:
- printf(" LAMBDA\n");
- dump_ast(depth + 1, node->_type.lambda.params);
- dump_ast(depth + 1, node->_type.lambda.ret);
- break;
-
case AST_TYPE_STRUCT:
printf(" STRUCT\n");
/* oh yeah, struc is at least right now just an ID that
@@ -1401,18 +1392,6 @@ static void __dump_ast(int depth, struct ast_node *node)
dump(depth, "}\n");
break;
- case AST_LAMBDA:
- dump(depth, "{LAMBDA:\n");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, node->_lambda.captures);
- dump_ast(depth + 1, node->_lambda.sign);
- dump_ast(depth + 1, node->_lambda.body);
-
- dump(depth, "}\n");
- break;
-
case AST_LAST:
dump(depth, "{LAST:");
dump_flags(node);
@@ -1564,13 +1543,13 @@ static void __dump_ast(int depth, struct ast_node *node)
dump(depth, "}\n");
break;
- case AST_TEMPLATE:
- dump(depth, "{TEMPLATE:");
+ case AST_TRAIT:
+ dump(depth, "{TRAIT:");
dump_flags(node);
putchar('\n');
- dump_ast(depth + 1, node->_template.id);
- dump_ast(depth + 1, node->_template.body);
+ dump_ast(depth + 1, node->_trait.id);
+ dump_ast(depth + 1, node->_trait.body);
dump(depth, "}\n");
break;
@@ -1654,6 +1633,10 @@ struct ast_node *clone_ast_node(struct ast_node *node)
clone_ast_node(node->_macro.body));
break;
+ case AST_MACRO_EXPANSION: new = gen_macro_expansion(clone_ast_node(node->_macro_expansion.id),
+ clone_ast_node(node->_macro_expansion.args));
+ break;
+
case AST_CAST: new = gen_cast(clone_ast_node(node->_cast.expr),
clone_ast_node(node->_cast.type));
break;
@@ -1681,12 +1664,6 @@ struct ast_node *clone_ast_node(struct ast_node *node)
break;
}
- case AST_LAMBDA: new = gen_lambda(clone_ast_node(
- node->_lambda.captures),
- clone_ast_node(node->_lambda.sign),
- clone_ast_node(node->_lambda.body));
- break;
-
case AST_FOR: new = gen_for(clone_ast_node(node->_for.pre),
clone_ast_node(node->_for.cond),
clone_ast_node(node->_for.post),
@@ -1729,11 +1706,11 @@ struct ast_node *clone_ast_node(struct ast_node *node)
node->_type.alias.actual);
break;
- case AST_TYPE_TEMPLATE:
- new = gen_type(AST_TYPE_TEMPLATE, NULL,
- node->_type.template.template,
+ case AST_TYPE_TRAIT:
+ new = gen_type(AST_TYPE_TRAIT, NULL,
+ node->_type.trait.trait,
/* ditto, should actual be cloned? */
- node->_type.template.actual);
+ node->_type.trait.actual);
break;
case AST_TYPE_ID:
new = gen_type(AST_TYPE_ID,
@@ -1784,13 +1761,6 @@ struct ast_node *clone_ast_node(struct ast_node *node)
clone_ast_node(node->_type.proc.ret));
break;
- case AST_TYPE_LAMBDA:
- new = gen_type(AST_TYPE_LAMBDA, NULL,
- clone_ast_node(
- node->_type.lambda.params),
- clone_ast_node(node->_type.lambda.ret));
- break;
-
case AST_TYPE_SIGN:
new = gen_type(AST_TYPE_SIGN, NULL,
clone_ast_node(node->_type.sign.params),
@@ -1876,9 +1846,9 @@ struct ast_node *clone_ast_node(struct ast_node *node)
clone_ast_node(node->_alias.type));
break;
- case AST_TEMPLATE:
- new = gen_template(clone_ast_node(node->_template.id),
- clone_ast_node(node->_template.body));
+ case AST_TRAIT:
+ new = gen_trait(clone_ast_node(node->_trait.id),
+ clone_ast_node(node->_trait.body));
break;
case AST_IF:
@@ -2078,21 +2048,6 @@ static int identical_var(int exact, struct ast_node *a, struct ast_node *b)
return 1;
}
-static int identical_lambda(int exact, struct ast_node *a, struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, a->_lambda.captures,
- b->_lambda.captures))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_lambda.sign, b->_lambda.sign))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_lambda.body, b->_lambda.body))
- return 0;
-
- return 1;
-}
-
static int identical_for(int exact, struct ast_node *a, struct ast_node *b)
{
if (!identical_ast_nodes(exact, a->_for.pre, b->_for.pre))
@@ -2145,15 +2100,15 @@ static int identical_type_alias(int exact, struct ast_node *a,
return 1;
}
-static int identical_type_template(int exact, struct ast_node *a,
+static int identical_type_trait(int exact, struct ast_node *a,
struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.template.template,
- b->_type.template.template))
+ if (!identical_ast_nodes(exact, a->_type.trait.trait,
+ b->_type.trait.trait))
return 0;
- if (!identical_ast_nodes(exact, a->_type.template.actual,
- b->_type.template.actual))
+ if (!identical_ast_nodes(exact, a->_type.trait.actual,
+ b->_type.trait.actual))
return 0;
return 1;
@@ -2189,20 +2144,6 @@ static int identical_type_proc(int exact, struct ast_node *a,
return 1;
}
-static int identical_type_lambda(int exact, struct ast_node *a,
- struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, a->_type.lambda.params,
- b->_type.lambda.params))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.lambda.ret,
- b->_type.lambda.ret))
- return 0;
-
- return 1;
-}
-
static int identical_type_sign(int exact, struct ast_node *a,
struct ast_node *b)
{
@@ -2293,13 +2234,12 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
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);
+ case AST_TYPE_TRAIT: ret = identical_type_trait(exact, a, b);
break;
case AST_TYPE_ID: ret = identical_type_id(exact, a, b); break;
case AST_TYPE_ARR: ret = identical_type_arr(exact, a, b); break;
case AST_TYPE_TYPEOF: ret = identical_type_typeof(exact, a, b); break;
case AST_TYPE_PROC: ret = identical_type_proc(exact, a, b); break;
- case AST_TYPE_LAMBDA: ret = identical_type_lambda(exact, a, b); break;
case AST_TYPE_SIGN: ret = identical_type_sign(exact, a, b); break;
case AST_TYPE_STRUCT: ret = identical_type_struct(exact, a, b); break;
case AST_TYPE_UNION: ret = identical_type_union(exact, a, b); break;
@@ -2440,12 +2380,12 @@ static int identical_alias(int exact, struct ast_node *a, struct ast_node *b)
return 1;
}
-static int identical_template(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_trait(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_template.id, b->_template.id))
+ if (!identical_ast_nodes(exact, a->_trait.id, b->_trait.id))
return 0;
- if (!identical_ast_nodes(exact, a->_template.body, b->_template.body))
+ if (!identical_ast_nodes(exact, a->_trait.body, b->_trait.body))
return 0;
return 1;
@@ -2523,9 +2463,9 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
case AST_CAST: ret = identical_cast(exact, a, b); break;
case AST_DEFER: ret = identical_defer(exact, a, b); break;
case AST_MACRO: ret = identical_macro(exact, a, b); break;
+ case AST_MACRO_EXPANSION: ret = identical_macro(exact, a, b); break;
case AST_PROC: ret = identical_proc(exact, a, b); break;
case AST_VAR: ret = identical_var(exact, a, b); break;
- case AST_LAMBDA: ret = identical_lambda(exact, a, b); break;
case AST_FOR: ret = identical_for(exact, a, b); break;
case AST_WHILE: ret = identical_while(exact, a, b); break;
case AST_CTRL: ret = identical_ctrl(exact, a, b); break;
@@ -2542,7 +2482,7 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
case AST_CONST: ret = identical_const(exact, a, b); break;
case AST_ID: ret = identical_id(exact, a, b); break;
case AST_ALIAS: ret = identical_alias(exact, a, b); break;
- case AST_TEMPLATE: ret = identical_template(exact, a, b); break;
+ case AST_TRAIT: ret = identical_trait(exact, a, b); break;
case AST_IF: ret = identical_if(exact, a, b); break;
case AST_EMPTY: break;
case AST_LAST: break;
@@ -2637,16 +2577,6 @@ static int call_on_var(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_lambda(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_lambda.captures, data);
- ret |= call(node->_lambda.sign, data);
- ret |= call(node->_lambda.body, data);
- return ret;
-}
-
static int call_on_for(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
@@ -2682,12 +2612,12 @@ static int call_on_alias(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_template(int (*call)(struct ast_node *,
+static int call_on_trait(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_template.id, data);
- ret |= call(node->_template.body, data);
+ ret |= call(node->_trait.id, data);
+ ret |= call(node->_trait.body, data);
return ret;
}
@@ -2757,12 +2687,12 @@ static int call_on_type_alias(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_type_template(int (*call)(struct ast_node *,
+static int call_on_type_trait(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.template.template, data);
- ret |= call(node->_type.template.actual, data);
+ ret |= call(node->_type.trait.trait, data);
+ ret |= call(node->_type.trait.actual, data);
return ret;
}
@@ -2812,15 +2742,6 @@ static int call_on_type_proc(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_type_lambda(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_type.lambda.params, data);
- ret |= call(node->_type.lambda.ret, data);
- return ret;
-}
-
static int call_on_type_sign(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
@@ -2868,7 +2789,7 @@ static int call_on_type(int (*call)(struct ast_node *,
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);
+ case AST_TYPE_TRAIT: ret = call_on_type_trait(call, node, data);
break;
case AST_TYPE_ID: ret = call_on_type_id(call, node, data); break;
case AST_TYPE_ARR: ret = call_on_type_arr(call, node, data); break;
@@ -2878,7 +2799,6 @@ static int call_on_type(int (*call)(struct ast_node *,
case AST_TYPE_STRUCT: ret = call_on_type_struct(call, node, data);
break;
case AST_TYPE_PROC: ret = call_on_type_proc(call, node, data); break;
- case AST_TYPE_LAMBDA: ret = call_on_type_lambda(call, node, data);
break;
case AST_TYPE_SIGN: ret = call_on_type_sign(call, node, data); break;
case AST_TYPE_POINTER: break;
@@ -2958,6 +2878,14 @@ static int call_on_fetch(int (*call)(struct ast_node *,
return ret;
}
+static int call_on_macro_expansion(int (*call)(struct ast_node *, void *), struct ast_node *node, void *data)
+{
+ int ret = 0;
+ ret |= call(node->_macro_expansion.id, data);
+ ret |= call(node->_macro_expansion.args, data);
+ return ret;
+}
+
/* I guess this works, but it's not exactly optimal as the caller sort of has to
* know when to continue to call on, and when it would cause an infinite loop.
* I.e. a call on an ID that is forwarded results in an infinite loop.
@@ -2983,12 +2911,11 @@ int ast_call_on(int (*call)(struct ast_node *,
case AST_CAST: ret = call_on_cast(call, node, data); break;
case AST_DEFER: ret = call_on_defer(call, node, data); break;
case AST_VAR: ret = call_on_var(call, node, data); break;
- case AST_LAMBDA: ret = call_on_lambda(call, node, data); break;
case AST_FOR: ret = call_on_for(call, node, data); break;
case AST_WHILE: ret = call_on_while(call, node, data); break;
case AST_RETURN: ret = call_on_return(call, node, data); break;
case AST_ALIAS: ret = call_on_alias(call, node, data); break;
- case AST_TEMPLATE: ret = call_on_template(call, node, data); break;
+ case AST_TRAIT: ret = call_on_trait(call, node, data); break;
case AST_IF: ret = call_on_if(call, node, data); break;
case AST_ENUM: ret = call_on_enum(call, node, data); break;
case AST_STRUCT: ret = call_on_struct(call, node, data); break;
@@ -3002,6 +2929,7 @@ int ast_call_on(int (*call)(struct ast_node *,
case AST_UNOP: ret = call_on_unop(call, node, data); break;
case AST_CALL: ret = call_on_call(call, node, data); break;
case AST_MACRO: ret = call_on_macro(call, node, data); break;
+ case AST_MACRO_EXPANSION: ret = call_on_macro_expansion(call, node, data); break;
case AST_PROC: ret = call_on_proc(call, node, data); break;
case AST_BLOCK: ret = call_on_block(call, node, data); break;
case AST_LAST: break;
diff --git a/src/debug.c b/src/debug.c
index 017f07f..ee410be 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -193,18 +193,18 @@ static void _type_str(FILE *fp, struct ast_node *type)
break;
}
- case AST_TYPE_TEMPLATE: {
- struct ast_node *template = type->_type.template.template;
- assert(template);
+ case AST_TYPE_TRAIT: {
+ struct ast_node *trait = type->_type.trait.trait;
+ assert(trait);
- struct ast_node *template_id = template->_template.id;
- struct ast_node *template_act = type->_type.template.actual;
- if (template_act) {
- fprintf(fp, "%s as ", template_id->_id.id);
- _type_str(fp, template_act);
+ struct ast_node *trait_id = trait->_trait.id;
+ struct ast_node *trait_act = type->_type.trait.actual;
+ if (trait_act) {
+ fprintf(fp, "%s as ", trait_id->_id.id);
+ _type_str(fp, trait_act);
}
else {
- fprintf(fp, "%s", template_id->_id.id);
+ fprintf(fp, "%s", trait_id->_id.id);
}
break;
}
@@ -284,7 +284,7 @@ char *type_str(struct ast_node *node)
char *buf = NULL; size_t size = 0;
FILE *memstream = open_memstream(&buf, &size);
- /* TODO: improve template detection */
+ /* TODO: improve trait detection */
/* we were given a plain type, pass it directly along to _type_str */
if (node->node_type == AST_TYPE)
_type_str(memstream, node);
diff --git a/src/lexer.l b/src/lexer.l
index 2857b94..50e7c1e 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -77,8 +77,6 @@ STRING \"(\\.|[^"\\])*\"
";" {return SEMICOLON;}
":" {return COLON;}
"!" {return BANG;}
-"##" {return PASTE;}
-"@" {return AT;}
"+" {return PLUS;}
"-" {return MINUS;}
@@ -86,7 +84,6 @@ STRING \"(\\.|[^"\\])*\"
"/" {return DIV;}
"%" {return REM;}
"^" {return XOR;}
-"^^" {return POW;}
'[^'\\]' {
/* regular character constant, 'a' */
@@ -124,9 +121,6 @@ STRING \"(\\.|[^"\\])*\"
"'" {return SQUOTE;}
"&" {return AND;}
-"&&" {return LAND;}
-"|" {return OR;}
-"||" {return LOR;}
"~" {return TILDE;}
"=" {return TO;}
@@ -147,10 +141,6 @@ STRING \"(\\.|[^"\\])*\"
"-=" {return MINUSSELF;}
"/=" {return DIVSELF;}
"%=" {return REMSELF;}
-"^=" {return XORSELF;}
-"^^=" {return POWSELF;}
-"&=" {return ORSELF;}
-"|=" {return ORSELF;}
"<<=" {return LSHIFTSELF;}
">>=" {return RSHIFTSELF;}
"..." {return ELLIPSIS;}
diff --git a/src/parser.y b/src/parser.y
index 9d55b72..8f5886c 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -49,18 +49,13 @@
%token TYPEOF "typeof"
/* typeof does sort of fit into sizeof, hmmm */
%token SIZEOF "sizeof"
-%token PASTE "##"
%token STAR "*"
%token DIV "/"
%token REM "%"
%token MINUS "-"
%token PLUS "+"
-%token POW "^^"
%token XOR "^"
%token AND "&"
-%token OR "|"
-%token LAND "&&"
-%token LOR "||"
%token TILDE "~"
%token LT "<"
%token GT ">"
@@ -75,13 +70,8 @@
%token STARSELF "*="
%token DIVSELF "/="
%token REMSELF "%="
-%token XORSELF "^="
-%token POWSELF "^^="
-%token ANDSELF "&="
-%token ORSELF "|="
%token LSHIFTSELF "<<="
%token RSHIFTSELF ">>="
-%token AT "@"
%token COMMA ","
%token PUB "pub"
%token STRUCT "struct"
@@ -122,13 +112,9 @@
%right "[" "]"
/* precedence */
%left ","
-%right "=" "+=" "-=" "*=" "/=" "%=" "<<=" ">>=" "&=" "^=" "|=" "^^="
-%left "^^"
-%left "||"
-%left "&&"
+%right "=" "+=" "-=" "*=" "/=" "%=" "<<=" ">>="
%left "==" "!="
%left "<" ">" "<=" ">="
-%left "|"
%left "^"
%left "&"
%left "<<" ">>"
@@ -144,19 +130,20 @@
%nterm <node> while do_while statement statements body references macro
%nterm <node> exprs if for case cases switch const
%nterm <node> func_sign type var_decl var
-%nterm <node> var_init proc template_elem template_elems types
-%nterm <node> alias template enum_val enums enum top unit id
-%nterm <node> embed param_decl union struct members struct_elem
+%nterm <node> var_init proc trait_elem trait_elems
+%nterm <node> alias trait enum_val enums enum top unit id
+%nterm <node> embed param_decl members struct_elem
%nterm <node> top_if const_if const_for defer goto assign
%nterm <node> construct construct_args construct_arg
-%nterm <node> generic generics statelet apply
+%nterm <node> statelet apply
-/* special handling for top level variables */
-%nterm <node> top_var_decl top_var_init top_var
+%nterm <node> tagged_struct anon_struct tagged_union anon_union
/* constant operations */
%nterm <node> const_expr const_unop const_binop
+%nterm <node> macro_expand
+
/* array stuff */
%nterm <node> arr arr_inits arr_init
@@ -270,12 +257,6 @@ binop
| expr "*" expr { $$ = gen_binop(AST_MUL, $1, $3); }
| expr "/" expr { $$ = gen_binop(AST_DIV, $1, $3); }
| expr "%" expr { $$ = gen_binop(AST_REM, $1, $3); }
- | expr "^" expr { $$ = gen_binop(AST_XOR, $1, $3); }
- | expr "^^" expr { $$ = gen_binop(AST_POW, $1, $3); }
- | expr "&" expr { $$ = gen_binop(AST_AND, $1, $3); }
- | expr "&&" expr { $$ = gen_binop(AST_LAND, $1, $3); }
- | expr "|" expr { $$ = gen_binop(AST_OR, $1, $3); }
- | expr "||" expr { $$ = gen_binop(AST_LOR, $1, $3); }
| expr "<<" expr { $$ = gen_binop(AST_LSHIFT, $1, $3); }
| expr ">>" expr { $$ = gen_binop(AST_RSHIFT, $1, $3); }
| expr "+=" expr { $$ = gen_binop(AST_ASSIGN_ADD, $1, $3); }
@@ -283,9 +264,6 @@ binop
| expr "*=" expr { $$ = gen_binop(AST_ASSIGN_MUL, $1, $3); }
| expr "/=" expr { $$ = gen_binop(AST_ASSIGN_DIV, $1, $3); }
| expr "%=" expr { $$ = gen_binop(AST_ASSIGN_REM, $1, $3); }
- | expr "&=" expr { $$ = gen_binop(AST_ASSIGN_AND, $1, $3); }
- | expr "|=" expr { $$ = gen_binop(AST_ASSIGN_OR, $1, $3); }
- | expr "^=" expr { $$ = gen_binop(AST_ASSIGN_XOR, $1, $3); }
| expr "<<=" expr {
$$ = gen_binop(AST_ASSIGN_LSHIFT, $1, $3);
}
@@ -347,12 +325,6 @@ const_binop
| const_expr "*" const_expr { $$ = gen_binop(AST_MUL, $1, $3); }
| const_expr "/" const_expr { $$ = gen_binop(AST_DIV, $1, $3); }
| const_expr "%" const_expr { $$ = gen_binop(AST_REM, $1, $3); }
- | const_expr "^" const_expr { $$ = gen_binop(AST_XOR, $1, $3); }
- | const_expr "^^" const_expr { $$ = gen_binop(AST_POW, $1, $3); }
- | const_expr "&" const_expr { $$ = gen_binop(AST_AND, $1, $3); }
- | const_expr "&&" const_expr { $$ = gen_binop(AST_LAND, $1, $3); }
- | const_expr "|" const_expr { $$ = gen_binop(AST_OR, $1, $3); }
- | const_expr "||" const_expr { $$ = gen_binop(AST_LOR, $1, $3); }
| const_expr "<<" const_expr { $$ = gen_binop(AST_LSHIFT, $1, $3); }
| const_expr ">>" const_expr { $$ = gen_binop(AST_RSHIFT, $1, $3); }
| const_expr "<" const_expr { $$ = gen_binop(AST_LT, $1, $3); }
@@ -389,13 +361,12 @@ expr
| expr "(" args ")" { $$ = gen_call($1, $3); }
| expr "(" ")" { $$ = gen_call($1, NULL); }
| expr "[" expr "]" { $$ = gen_call($1, $3); /** @todo add arr access */}
- | apply "(" args ")" { $$ = gen_call($1, $3); /* macro call */}
- | apply "(" ")" { $$ = gen_call($1, NULL); /* macro call */}
| "(" var_init ")" { $$ = $2; }
| "sizeof" expr { $$ = gen_sizeof($2); }
| expr "as" type { $$ = gen_cast($1, $3); }
| id "::" type { $$ = gen_fetch($1, $3); }
| "as" type { $$ = gen_as($2); }
+ | macro_expand
| construct
| assign
| embed
@@ -420,7 +391,7 @@ statelet
| "return" { $$ = gen_return(NULL); }
| "break" { $$ = gen_ctrl(AST_CTRL_BREAK, to_src_loc(&yylloc)); }
| "continue" { $$ = gen_ctrl(AST_CTRL_CONTINUE, to_src_loc(&yylloc)); }
- | template
+ | trait
| import
| alias
| exprs
@@ -449,7 +420,8 @@ statement
| while
| do_while
| body
- | struct
+ | tagged_struct
+ | tagged_union
| for
| defer
| if
@@ -580,9 +552,8 @@ type
$$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
$$->_type.next = $2;
}
- | apply "[" types "]" {
- $$ = gen_type(AST_TYPE_GENERIC, $1, $3, NULL);
- }
+ | anon_struct { $$ = $1; }
+ | anon_union { $$ = $1; }
| "*" type {
$$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
$$->_type.next = $2;
@@ -627,63 +598,59 @@ proc
}
struct_elem
- : var_decl { $$ = $1; }
+ : var_decl
+ | macro_expand
+ ;
members
: struct_elem ";" members { $$ = $1; $1->next = $3; }
| struct_elem ";" { $$ = $1; }
-union
+tagged_union
: "union" id "{" members "}" {
$$ = gen_union($2, NULL, $4);
}
- | "union" id "(" generics ")" "{" members "}" {
- $$ = gen_union($2, $4, $7);
- }
-generic
- : type id { $$ = gen_alias($1, $2); }
+anon_union
+ : "union" "{" members "}" { $$ = gen_union(NULL, NULL, $3); }
+ | "union" macro_expand { $$ = gen_union(NULL, NULL, $2); }
-generics
- : generic "," generics { $$ = $1; $$->next = $3; }
- | generic { $$ = $1; }
+macro_expand
+ : apply "(" ")" { $$ = gen_macro_expansion($1, NULL); }
+ | apply "(" args ")" { $$ = gen_macro_expansion($1, $3); }
-struct
+tagged_struct
: "struct" id "{" members "}" {
$$ = gen_struct($2, NULL, $4);
}
- | "struct" id "[" generics "]" "{" members "}" {
- $$ = gen_struct($2, $4, $7);
- }
-/* since traits aren't generic, they don't have to implement anything, meaning
- * we can keep a pretty clean separation between procs and supertraits */
-template_elem
- : id ";" { $$ = $1; }
- | id func_sign ";" { $$ = gen_proc($1, $2, NULL); }
- | var_decl ";" { $$ = $1; }
- | union { $$ = $1; }
+anon_struct
+ : "struct" "{" members "}" { $$ = gen_struct(NULL, NULL, $3); }
+ | "struct" macro_expand { $$ = gen_struct(NULL, NULL, $2); }
-template_elems
- : template_elem template_elems { $$ = $1; $1->next = $2; }
- | template_elem { $$ = $1; }
+trait_elem
+ : id
+ | id func_sign { $$ = gen_proc($1, $2, NULL); }
+ | var_decl
+ | macro_expand
-types
- : type "," types { $$ = $1; $1->next = $3; }
- | type { $$ = $1; }
+trait_elems
+ : trait_elem ";" trait_elems { $$ = $1; $1->next = $3; }
+ | trait_elem ";"
+ | trait_elem
alias
: "typedef" id type { $$ = gen_alias($2, $3); }
/* we'll parse the arg list later in the AST and check that each node is of some
* specific type */
-template
- : "typedef" id "{" template_elems "}" {
- $$ = gen_template($2, $4);
+trait
+ : "typedef" id "{" trait_elems "}" {
+ $$ = gen_trait($2, $4);
}
| "typedef" id "{" "}" {
/* should match anything, but doesn't implement anything */
- $$ = gen_template($2, NULL);
+ $$ = gen_trait($2, NULL);
}
enum_val
@@ -716,43 +683,26 @@ top_if
ast_set_flags($$, AST_FLAG_UNHYGIENIC);
}
-top_var_decl
- : type id { $$ = gen_var($2, $1, NULL); }
-
-top_var_init
- : top_var_decl "=" const_expr { $$ = $1; $$->_var.init = $3; }
- | "const" id "=" const_expr { $$ = gen_var($2, NULL, $4); }
- | "mut" id "=" const_expr { $$ = gen_var($2, NULL, $4); }
-
-top_var
- : top_var_decl { $$ = $1; }
- | top_var_init { $$ = $1; }
-
/* slightly silly to allow stray semicolons at a top level, but seems to help
* with recovering from certain syntax errors */
top
: enum { $$ = $1; }
| proc { $$ = $1; }
- | struct { $$ = $1; }
- | union { $$ = $1; }
+ | tagged_struct { $$ = $1; }
+ | tagged_union { $$ = $1; }
| macro { $$ = $1; }
| top_if { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); }
- | top_var { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); }
| import { $$ = $1; }
| alias { $$ = $1; }
- | template { $$ = $1; }
+ | trait { $$ = $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" tagged_struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
+ | "pub" tagged_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); }
| "pub" alias { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
- | "pub" template { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
- | "pub" top_var {
- $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC);
- ast_set_flags($$, AST_FLAG_CONST);
- }
+ | "pub" trait { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| ";" { $$ = gen_empty(); }
| error {
$$ = gen_empty();
diff --git a/src/scope.c b/src/scope.c
index b6ce773..8d9ada3 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -22,7 +22,7 @@ static int generics_trait_type(struct ast_node *generics)
if (!generics)
return 0;
- if (actual_type(generics)->_type.kind == AST_TYPE_TEMPLATE)
+ if (actual_type(generics)->_type.kind == AST_TYPE_TRAIT)
return 1;
return generics_trait_type(generics->_type.next);
@@ -40,8 +40,8 @@ static int generic_type(struct ast_node *type)
return generics_trait_type(type->_type.unio.impls);
}
- if (type->_type.kind == AST_TYPE_TEMPLATE)
- return type->_type.template.actual == NULL;
+ if (type->_type.kind == AST_TYPE_TRAIT)
+ return type->_type.trait.actual == NULL;
return generic_type(type->_type.next);
}
@@ -79,7 +79,7 @@ int fully_qualified(struct ast_node *type)
if (!type)
return 1;
- assert(type->_type.kind != AST_TYPE_TEMPLATE);
+ assert(type->_type.kind != AST_TYPE_TRAIT);
if (type->_type.kind == AST_TYPE_STRUCT) {
if (!ast_flags(type, AST_FLAG_GENERIC))
return 1;
@@ -394,8 +394,8 @@ static struct ast_node *proc_resolve(struct scope *scope,
if (implements(0, scope, args->type, fallback->type)) {
/* my idea is that we could lock each node individually and
* allow multithreading scopes, but I realize that recursively
- * checking templates might cause a lock... */
- init_template_type(fallback->type, fallback->type, args->type);
+ * checking traits might cause a lock... */
+ init_trait_type(fallback->type, fallback->type, args->type);
return proc_resolve(scope, fallback->proc, args->next);
}
@@ -520,7 +520,7 @@ void destroy_scope(struct scope *scope)
destroy_visible(scope, scope->unions);
destroy_visible(scope, scope->structs);
destroy_visible(scope, scope->aliases);
- destroy_visible(scope, scope->templates);
+ destroy_visible(scope, scope->traits);
struct scope *prev = scope->children, *cur;
if (prev)
@@ -580,7 +580,7 @@ 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);
+CREATE_VISIBLE(create_trait, traits, AST_TRAIT);
/* TODO: check for identical names in the scope? */
#define REFERENCE_VISIBLE(name, list, ast_type) \
@@ -606,7 +606,7 @@ 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);
+REFERENCE_VISIBLE(reference_trait, traits, AST_TRAIT);
/* does NOT walk the scope tree upward if it doesn't find the var in the scope
* */
@@ -633,7 +633,7 @@ 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);
+FIND_VISIBLE(scope_find_trait, traits, AST_TRAIT, _trait);
/* note that these return the first match for the ID, and as such might not be
* what should be called. */
FIND_VISIBLE(scope_find_var, vars, AST_VAR, _var);
@@ -660,7 +660,7 @@ struct ast_node *scope_find(struct scope *scope, struct ast_node *id)
if (found)
return found;
- found = scope_find_template(scope, id);
+ found = scope_find_trait(scope, id);
if (found)
return found;
@@ -695,7 +695,7 @@ struct visible *create_type(struct scope *scope, struct ast_node *type)
switch (type->node_type) {
case AST_TYPE: return create_builtin(scope, type);
case AST_ALIAS: return create_alias(scope, type);
- case AST_TEMPLATE: return create_template(scope, type);
+ case AST_TRAIT: return create_trait(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);
@@ -710,7 +710,7 @@ int reference_type(int public, struct scope *scope, struct visible *visible)
switch (visible->node->node_type) {
case AST_TYPE: return reference_builtin(public, scope, visible);
case AST_ALIAS: return reference_alias(public, scope, visible);
- case AST_TEMPLATE: return reference_template(public, scope, visible);
+ case AST_TRAIT: return reference_trait(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);
@@ -766,7 +766,7 @@ struct ast_node *scope_find_type(struct scope *scope, struct ast_node *id)
if (found)
return found;
- found = scope_find_template(scope, id);
+ found = scope_find_trait(scope, id);
if (found)
return found;
@@ -775,30 +775,30 @@ struct ast_node *scope_find_type(struct scope *scope, struct ast_node *id)
ADD_VISIBLE(scope_add_var, var, AST_VAR, _var);
ADD_VISIBLE(scope_add_alias, alias, AST_ALIAS, _alias);
-ADD_VISIBLE(scope_add_template, template, AST_TEMPLATE, _template);
+ADD_VISIBLE(scope_add_trait, trait, AST_TRAIT, _trait);
-static int add_implementation(struct ast_node *template, struct ast_node *type)
+static int add_implementation(struct ast_node *trait, struct ast_node *type)
{
assert(
- template->node_type == AST_TEMPLATE &&
+ trait->node_type == AST_TRAIT &&
type->node_type == AST_TYPE);
- struct template_implemented *by = calloc(1, sizeof(*type));
+ struct trait_implemented *by = calloc(1, sizeof(*type));
if (!by) {
internal_error("failed allocating memory for implementation");
return 1;
}
by->type = type;
- by->next = template->_template.impl_by;
- template->_template.impl_by = by;
+ by->next = trait->_trait.impl_by;
+ trait->_trait.impl_by = by;
return 0;
}
-static void remove_implementation(struct ast_node *template,
+static void remove_implementation(struct ast_node *trait,
struct ast_node *type)
{
- assert(template->node_type == AST_TEMPLATE);
- struct template_implemented *prev = template->_template.impl_by, *cur;
+ assert(trait->node_type == AST_TRAIT);
+ struct trait_implemented *prev = trait->_trait.impl_by, *cur;
if (prev)
do {
cur = prev->next;
@@ -806,7 +806,7 @@ static void remove_implementation(struct ast_node *template,
break;
if (identical_ast_nodes(0, cur->type, type)) {
- struct template_implemented *next = cur->next;
+ struct trait_implemented *next = cur->next;
prev->next = next;
free(cur);
return;
@@ -814,18 +814,18 @@ static void remove_implementation(struct ast_node *template,
} while ((prev = cur));
}
-static int find_implementation(struct ast_node *template, struct ast_node *type)
+static int find_implementation(struct ast_node *trait, struct ast_node *type)
{
if (!type)
return 0;
- assert(template->node_type == AST_TEMPLATE);
- if (type->_type.kind == AST_TYPE_TEMPLATE)
- return find_implementation(template,
- type->_type.template.actual);
+ assert(trait->node_type == AST_TRAIT);
+ if (type->_type.kind == AST_TYPE_TRAIT)
+ return find_implementation(trait,
+ type->_type.trait.actual);
if (type->_type.kind == AST_TYPE_ALIAS)
- return find_implementation(template, type->_type.alias.actual);
+ return find_implementation(trait, type->_type.alias.actual);
/* I'm not 100% sold on having to handle these special cases multiple
* times in different places, but I'm not sure what alternatives I have.
@@ -834,9 +834,9 @@ static int find_implementation(struct ast_node *template, struct ast_node *type)
* and keep a reference to the original or something without too much
* work? TODO */
if (type->_type.kind == AST_TYPE_TYPEOF)
- return find_implementation(template, type->_type.typeo.actual);
+ return find_implementation(trait, type->_type.typeo.actual);
- struct template_implemented *prev = template->_template.impl_by, *cur;
+ struct trait_implemented *prev = trait->_trait.impl_by, *cur;
if (prev)
do {
cur = prev->next;
@@ -898,8 +898,8 @@ static int implements_proc(enum match_flags flags, struct scope *scope,
struct ast_node *params = sign->_type.sign.params;
struct ast_node *ret = sign->_type.sign.ret;
- init_template_types(params, param_type, arg_type);
- init_template_type(ret, param_type, arg_type);
+ init_trait_types(params, param_type, arg_type);
+ init_trait_type(ret, param_type, arg_type);
struct ast_node *impl = match_proc(1, scope, id, params);
if (!impl)
@@ -907,10 +907,10 @@ static int implements_proc(enum match_flags flags, struct scope *scope,
struct ast_node *impl_ret = impl->_proc.sign->_type.sign.ret;
/* note important distinction between when to use ->type and when to not
- * in short: ->type can be a template or alias, not using it is the type
+ * in short: ->type can be a trait or alias, not using it is the type
* before being resolved.
*/
- /* TODO: detect loops, such as when two template return params rely on
+ /* TODO: detect loops, such as when two trait return params rely on
* eachother */
if (!implements(flags, scope, impl_ret, ret)) {
char *irt = type_str(impl_ret);
@@ -942,29 +942,29 @@ static int implements_var(enum match_flags flags, struct scope *scope,
return 0;
}
-static int implements_template(enum match_flags flags, struct scope *scope,
+static int implements_trait(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type,
struct ast_node *param_type)
{
- assert(param_type->_type.kind == AST_TYPE_TEMPLATE);
- if (param_type->_type.template.actual)
+ assert(param_type->_type.kind == AST_TYPE_TRAIT);
+ if (param_type->_type.trait.actual)
return implements(flags, scope, arg_type,
- param_type->_type.template.actual);
+ param_type->_type.trait.actual);
- struct ast_node *template = param_type->_type.template.template;
- /* if we already know we implement this template, nothing to do */
- if (find_implementation(template, arg_type))
+ struct ast_node *trait = param_type->_type.trait.trait;
+ /* if we already know we implement this trait, nothing to do */
+ if (find_implementation(trait, arg_type))
return 1;
- /* optimistically assume we implement type template */
- /* TODO: this optimism might be questionable, as some template might rely
- * on another template being implemented by the same type.
+ /* optimistically assume we implement type trait */
+ /* TODO: this optimism might be questionable, as some trait might rely
+ * on another trait being implemented by the same type.
* The other type will return an error message, and the compilation will
* fail, but the error messages generated might be misleading. Look into
* it at some point. */
- add_implementation(template, arg_type);
+ add_implementation(trait, arg_type);
- struct ast_node *body = template->_template.body;
+ struct ast_node *body = trait->_trait.body;
/* if the body is empty, match */
struct ast_node *elem = body;
@@ -1002,7 +1002,7 @@ static int implements_template(enum match_flags flags, struct scope *scope,
else {
semantic_error(scope->fctx, elem,
- "illegal template element");
+ "illegal trait element");
goto not_implemented;
}
} while ((elem = elem->next));
@@ -1010,7 +1010,7 @@ static int implements_template(enum match_flags flags, struct scope *scope,
return 1;
not_implemented:
- remove_implementation(template, arg_type);
+ remove_implementation(trait, arg_type);
return 0;
}
@@ -1076,27 +1076,27 @@ int implements(enum match_flags flags, struct scope *scope,
return implements_typeof(flags, scope, arg_type, param_type);
}
- /* having the arg be a template is a bit of a special case */
- if (arg_type->_type.kind == AST_TYPE_TEMPLATE) {
- if (arg_type->_type.template.actual == NULL)
+ /* having the arg be a trait is a bit of a special case */
+ if (arg_type->_type.kind == AST_TYPE_TRAIT) {
+ if (arg_type->_type.trait.actual == NULL)
return types_match(arg_type, param_type);
- return implements(flags, scope, arg_type->_type.template.actual,
+ return implements(flags, scope, arg_type->_type.trait.actual,
param_type);
}
- /* TODO: do aliases and templates have to be converted to types? Are
- * there any situations where a template will have to be followed by
+ /* TODO: do aliases and traits have to be converted to types? Are
+ * there any situations where a trait will have to be followed by
* some other type? */
- /* if the parameter type is not a template, it's an actual type and therefore the
+ /* if the parameter type is not a trait, it's an actual type and therefore the
* argument type must be identical to it */
- if (param_type->_type.kind == AST_TYPE_TEMPLATE) {
- if (param_type->_type.template.actual == NULL)
- return implements_template(flags, scope, arg_type,
+ if (param_type->_type.kind == AST_TYPE_TRAIT) {
+ if (param_type->_type.trait.actual == NULL)
+ return implements_trait(flags, scope, arg_type,
param_type);
return implements(flags, scope, arg_type,
- param_type->_type.template.actual);
+ param_type->_type.trait.actual);
}
if (param_type->_type.kind == AST_TYPE_POINTER) {
@@ -1136,7 +1136,7 @@ static int match_args(enum match_flags flags, struct scope *scope, int variadic,
if (!implements(flags, scope, args->type, params->type))
return 0;
- init_template_type(params->type, params->type, args->type);
+ init_trait_type(params->type, params->type, args->type);
params = params->next;
args = args->next;
@@ -1347,7 +1347,7 @@ FIND_FILE_VISIBLE(file_scope_find_proc, proc);
FIND_FILE_VISIBLE(file_scope_find_macro, macro);
FIND_FILE_VISIBLE(file_scope_find_alias, alias);
-FIND_FILE_VISIBLE(file_scope_find_template, template);
+FIND_FILE_VISIBLE(file_scope_find_trait, trait);
struct ast_node *file_scope_find(struct scope *scope, struct ast_node *id)
{
@@ -1371,7 +1371,7 @@ struct ast_node *file_scope_find(struct scope *scope, struct ast_node *id)
if (found)
return found;
- found = file_scope_find_template(scope, id);
+ found = file_scope_find_trait(scope, id);
if (found)
return found;
@@ -1386,14 +1386,14 @@ struct ast_node *scope_resolve_macro(struct scope *scope, struct ast_node *call)
return match_macro(0, scope, id, args);
}
-static int template_contains_proc(enum match_flags flags, struct scope *scope,
- struct ast_node *template,
+static int trait_contains_proc(enum match_flags flags, struct scope *scope,
+ struct ast_node *trait,
struct ast_node *id, struct ast_node *args)
{
- assert(template->_type.kind == AST_TYPE_TEMPLATE);
- template = template->_type.template.template;
+ assert(trait->_type.kind == AST_TYPE_TRAIT);
+ trait = trait->_type.trait.trait;
- struct ast_node *elem = template->_template.body;
+ struct ast_node *elem = trait->_trait.body;
if (elem)
do {
if (elem->node_type != AST_PROC)
@@ -1426,15 +1426,15 @@ struct ast_node *scope_resolve_proc(struct scope *scope, struct ast_node *call)
/* TODO: this prints out an error for each scope we run through, figure
* out where we should check for this stuff so only a single error is
* printed */
- /* loop over arguments, if any of them are templated check that the
- * found proc can be found in the template */
+ /* loop over arguments, if any of them are traitd check that the
+ * found proc can be found in the trait */
struct ast_node *arg = args;
while (arg) {
- struct ast_node *template = extract_template(arg->type);
- if (!template)
+ struct ast_node *trait = extract_trait(arg->type);
+ if (!trait)
goto next;
- if (!template_contains_proc(MATCH_CALL, scope, template, id,
+ if (!trait_contains_proc(MATCH_CALL, scope, trait, id,
args)) {
char *cstr = call_str(call);
char *tstr = type_str(arg);
@@ -1476,7 +1476,7 @@ struct ast_node *scope_resolve_actual(struct scope *scope,
continue;
assert(!ast_flags(actual, AST_FLAG_VARIADIC));
- /* could also check that arguments aren't templates */
+ /* could also check that arguments aren't traits */
struct ast_node *args = call->_call.args;
struct ast_node *sign = actual->_proc.sign;
struct ast_node *params = sign->_type.sign.params;
@@ -1559,8 +1559,8 @@ struct ast_node *scope_resolve_type(struct scope *scope, struct ast_node *type)
id = type->_alias.id;
break;
- case AST_TEMPLATE:
- id = type->_template.id;
+ case AST_TRAIT:
+ id = type->_trait.id;
break;
case AST_STRUCT: