diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-03-27 03:18:48 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-03-27 03:18:48 +0300 |
| commit | 78cf00cb506cb86112cb715e4d2d69ec11b20c42 (patch) | |
| tree | 32a1fd3d1e60343cb1e654900c2d4dedca5e938b /src/scope.c | |
| parent | 9fb179ab999c3b98caabca09b30c409dc5dd3b3d (diff) | |
| download | ek-78cf00cb506cb86112cb715e4d2d69ec11b20c42.tar.gz ek-78cf00cb506cb86112cb715e4d2d69ec11b20c42.zip | |
change typeof to be a full time type
Diffstat (limited to 'src/scope.c')
| -rw-r--r-- | src/scope.c | 101 |
1 files changed, 82 insertions, 19 deletions
diff --git a/src/scope.c b/src/scope.c index 721a31e..eca425b 100644 --- a/src/scope.c +++ b/src/scope.c @@ -386,7 +386,26 @@ static void remove_implementation(struct ast_node *template, static int find_implementation(struct ast_node *template, 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); + + if (type->_type.kind == AST_TYPE_ALIAS) + return find_implementation(template, 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. + * For debugging purposes, maintaining as much info about the original + * code is useful, but I wonder if I can somehow maybe clone this stuff + * 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); + struct template_implemented *prev = template->_template.impl_by, *cur; if (prev) do { @@ -448,8 +467,8 @@ static int implements_proc(struct scope *scope, struct ast_node *arg_type, struct ast_node *params = sign->_type.sign.params; struct ast_node *ret = sign->_type.sign.ret; - replace_param_types(params, param_type, arg_type); - replace_param_types(ret, param_type, arg_type); + init_template_types(params, param_type, arg_type); + init_template_type(ret, param_type, arg_type); struct ast_node *impl = match_proc(1, scope, id, params); if (!impl) @@ -552,6 +571,40 @@ not_implemented: return 0; } +static int implements_alias(struct scope *scope, struct ast_node *arg_type, + struct ast_node *param_type) +{ + struct ast_node *a_act = NULL, *p_act = NULL; + if (arg_type->_type.kind == AST_TYPE_ALIAS) + a_act = arg_type->_type.alias.actual; + else + a_act = arg_type; + + if (param_type->_type.kind == AST_TYPE_ALIAS) + p_act = param_type->_type.alias.actual; + else + p_act = param_type; + + return implements(scope, a_act, p_act); +} + +static int implements_typeof(struct scope *scope, struct ast_node *arg_type, + struct ast_node *param_type) +{ + struct ast_node *a_act = NULL, *p_act = NULL; + if (arg_type->_type.kind == AST_TYPE_TYPEOF) + a_act = arg_type->_type.typeo.actual; + else + a_act = arg_type; + + if (param_type->_type.kind == AST_TYPE_TYPEOF) + p_act = param_type->_type.typeo.actual; + else + p_act = param_type; + + return implements(scope, a_act, p_act); +} + int implements(struct scope *scope, struct ast_node *arg_type, struct ast_node *param_type) { @@ -571,18 +624,22 @@ int implements(struct scope *scope, /* at this point, we should always have some type for the argument */ assert(arg_type); - if (param_type->_type.kind == AST_TYPE_ALIAS) { + if (param_type->_type.kind == AST_TYPE_ALIAS || + arg_type->_type.kind == AST_TYPE_ALIAS) { assert(param_type->_type.next == NULL); - return implements(scope, arg_type, - param_type->_type.alias.actual); + return implements_alias(scope, arg_type, param_type); } - if (arg_type->_type.kind == AST_TYPE_ALIAS) { - assert(arg_type->_type.next == NULL); - return implements(scope, arg_type->_type.alias.actual, - param_type); + if (param_type->_type.kind == AST_TYPE_TYPEOF || + arg_type->_type.kind == AST_TYPE_TYPEOF) { + return implements_typeof(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) + return implements(scope, arg_type->_type.template.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 * some other type? */ @@ -817,16 +874,18 @@ int scope_add_existing_proc(struct scope *scope, struct visible *visible) return 0; } -#define FIND_FILE_VISIBLE(name, obj_type) \ - struct ast_node *name(struct scope *scope, struct ast_node *id) \ - { \ - assert(id->node_type == AST_ID); \ - struct ast_node *found = scope_find_##obj_type(scope, id); \ - if (found) \ - return found; \ - if (!scope_flags(scope, SCOPE_FILE)) \ - return file_scope_find_##obj_type(scope->parent, id); \ - return NULL; \ +#define FIND_FILE_VISIBLE(name, obj_type) \ + struct ast_node *name(struct scope *scope, struct ast_node *id) \ + { \ + assert(id->node_type == AST_ID); \ + struct ast_node *found = scope_find_##obj_type(scope, id); \ + if (found) { \ + return found; \ + } \ + if (!scope_flags(scope, SCOPE_FILE)) { \ + return file_scope_find_##obj_type(scope->parent, id); \ + } \ + return NULL; \ } struct ast_node *file_scope_find_type(struct scope *scope, @@ -860,6 +919,10 @@ struct ast_node *file_scope_find(struct scope *scope, struct ast_node *id) if (found) return found; + found = file_scope_find_override(scope, id); + if (found) + return found; + found = file_scope_find_proc(scope, id); if (found) return found; |
