diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/actualize.c | 130 | ||||
| -rw-r--r-- | src/ast.c | 258 | ||||
| -rw-r--r-- | src/debug.c | 20 | ||||
| -rw-r--r-- | src/lexer.l | 10 | ||||
| -rw-r--r-- | src/parser.y | 144 | ||||
| -rw-r--r-- | src/scope.c | 154 |
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; } } @@ -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: |
