diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-04-01 14:51:20 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-04-01 14:51:20 +0300 |
| commit | 4642bedb436981e92e3312f06bfcb2eb34074596 (patch) | |
| tree | cc5bf868a391c9880b9917eed44b20e4df535d1d | |
| parent | 0132be5b71f3fe161b2fcda201c945d30bd8d1a5 (diff) | |
| download | ek-4642bedb436981e92e3312f06bfcb2eb34074596.tar.gz ek-4642bedb436981e92e3312f06bfcb2eb34074596.zip | |
disallow certain kinds of types in templates
| -rw-r--r-- | include/cu/scope.h | 3 | ||||
| -rw-r--r-- | src/actualize.c | 44 | ||||
| -rw-r--r-- | src/scope.c | 30 | ||||
| -rw-r--r-- | tests/resolve.cu | 6 |
4 files changed, 59 insertions, 24 deletions
diff --git a/include/cu/scope.h b/include/cu/scope.h index 5a75427..d8fd2c4 100644 --- a/include/cu/scope.h +++ b/include/cu/scope.h @@ -166,4 +166,7 @@ struct ast_node *file_scope_resolve_call(struct scope *scope, int implements(enum match_flags flags, struct scope *scope, struct ast_node *arg_type, struct ast_node *param_type); +int primitive_type(struct ast_node *type); +int fully_qualified(struct ast_node *type); + #endif /* SCOPE_H */ diff --git a/src/actualize.c b/src/actualize.c index 0c7a378..4d1d449 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -21,6 +21,7 @@ enum act_flags { ACT_IN_SWITCH = (1 << 1), ACT_ONLY_TYPES = (1 << 2), ACT_HAS_RETURN = (1 << 3), + ACT_REQUIRE_FULLY_QUALIFIED = (1 << 4), }; struct act_state { @@ -998,6 +999,7 @@ static int actualize_proc(struct act_state *state, * think */ struct act_state new_state = {0}; new_state.cur_proc = actual; + act_set_flags(&new_state, ACT_REQUIRE_FULLY_QUALIFIED); /* actualize body */ ret |= actualize(&new_state, sign->scope, actual->_proc.body); if (!act_flags(&new_state, ACT_HAS_RETURN)) { @@ -1358,7 +1360,23 @@ static int actualize_type(struct act_state *state, if (actualize(state, scope, types)) EXIT_ACT(-1); - /* TODO: check that all params are fully qualified */ + while (types) { + if (!primitive_type(types)) { + semantic_error(scope->fctx, types, + "only primitive types allowed in template initialization"); + EXIT_ACT(-1); + } + + if (act_flags(state, ACT_REQUIRE_FULLY_QUALIFIED)) { + if (!fully_qualified(types)) { + semantic_error(scope->fctx, types, + "context requires fully qualified types"); + EXIT_ACT(-1); + } + } + types = types->next; + } + break; } @@ -1611,14 +1629,26 @@ static int init_struct(struct act_state *state, struct scope *scope, struct ast_node *actual_type(struct ast_node *type) { assert(type->node_type == AST_TYPE); - if (type->_type.kind == AST_TYPE_ALIAS) - return actual_type(type->_type.alias.actual); + if (type->_type.kind == AST_TYPE_ALIAS) { + if (type->_type.alias.actual) + return actual_type(type->_type.alias.actual); - if (type->_type.kind == AST_TYPE_TEMPLATE) - return actual_type(type->_type.template.actual); + return type; + } - if (type->_type.kind == AST_TYPE_TYPEOF) - return actual_type(type->_type.typeo.actual); + if (type->_type.kind == AST_TYPE_TEMPLATE) { + if (type->_type.template.actual) + return actual_type(type->_type.template.actual); + + return type; + } + + if (type->_type.kind == AST_TYPE_TYPEOF) { + if (type->_type.typeo.actual) + return actual_type(type->_type.typeo.actual); + + return type; + } return type; } diff --git a/src/scope.c b/src/scope.c index b560e5f..c2b8aab 100644 --- a/src/scope.c +++ b/src/scope.c @@ -22,7 +22,7 @@ static int generics_trait_type(struct ast_node *generics) return generics_trait_type(generics->_type.next); } -static int generic_type(struct scope *scope, struct ast_node *type) +static int generic_type(struct ast_node *type) { if (!type) return 0; @@ -37,10 +37,10 @@ static int generic_type(struct scope *scope, struct ast_node *type) if (type->_type.kind == AST_TYPE_TEMPLATE) return type->_type.template.actual == NULL; - return generic_type(scope, type->_type.next); + return generic_type(type->_type.next); } -static int referential_type(struct scope *scope, struct ast_node *type) +static int referential_type(struct ast_node *type) { if (!type) return 0; @@ -51,24 +51,24 @@ static int referential_type(struct scope *scope, struct ast_node *type) if (type->_type.kind == AST_TYPE_MEMBER) return 1; - return referential_type(scope, type->_type.next); + return referential_type(type->_type.next); } -static int primitive_type(struct scope *scope, struct ast_node *type) +int primitive_type(struct ast_node *type) { if (!type) return 1; - if (referential_type(scope, type)) + if (referential_type(type)) return 0; - if (generic_type(scope, type)) + if (generic_type(type)) return 0; return 1; } -static int fully_qualified(struct ast_node *type) +int fully_qualified(struct ast_node *type) { if (!type) return 1; @@ -123,8 +123,9 @@ static int compare_primitives(struct ast_node *a, struct ast_node *b); * otherwise use find_primitive() to get which primitive matches. * (are these names inverted from their intention? I'm not sure) */ -static struct param_node *match_primitive(struct scope *scope, struct proc_node *node, - struct ast_node *type) +static struct param_node *match_primitive(struct scope *scope, + struct proc_node *node, + struct ast_node *type) { struct param_node *param = node->primitives; while (param) { @@ -194,7 +195,8 @@ static int compare_primitives(struct ast_node *a, struct ast_node *b) return 1; if (a->_type.kind == AST_TYPE_STRUCT) - return compare_impls(a->_type.struc.impls, b->_type.struc.impls); + return compare_impls(a->_type.struc.impls, + b->_type.struc.impls); if (a->_type.kind == AST_TYPE_UNION) return compare_impls(a->_type.unio.impls, b->_type.unio.impls); @@ -262,9 +264,9 @@ static int add_next_resolve(struct scope *scope, struct ast_node *proc, } assert(params->node_type == AST_VAR); - if (primitive_type(scope, params->type)) { + if (primitive_type(params->type)) { struct param_node *match = match_primitive(scope, node, - params->type); + params->type); if (match) return add_next_resolve(scope, proc, match->proc, params->next); @@ -276,7 +278,7 @@ static int add_next_resolve(struct scope *scope, struct ast_node *proc, return add_next_resolve(scope, proc, next, params->next); } - if (referential_type(scope, params->type)) { + if (referential_type(params->type)) { /* TODO: I don't think there's a good way to check if the * referential types are identical, but could be worth a shot */ if (!node->referential) { diff --git a/tests/resolve.cu b/tests/resolve.cu index aee8bc4..1be0916 100644 --- a/tests/resolve.cu +++ b/tests/resolve.cu @@ -23,13 +23,13 @@ struct other_generic(T1 A) { // TODO: traits shouldn't be allowed in template instantiation //some_func(a generic(A, A)){6;} //some_func(generic(generic, generic)){1;} -some_func(generic(generic, i64)){2;} -some_func(generic(i64, generic)){3;} +//some_func(generic(generic, i64)){2;} +//some_func(generic(i64, generic)){3;} //some_func(generic(i64, i64)){4;} some_func(generic){5;} main(){ // TODO: not fully qualified types in bodies should cause an error - a generic(i64, u32); + a generic(i64, generic); some_func(a); } |
