aboutsummaryrefslogtreecommitdiff
path: root/src/scope.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-03-27 03:18:48 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2023-03-27 03:18:48 +0300
commit78cf00cb506cb86112cb715e4d2d69ec11b20c42 (patch)
tree32a1fd3d1e60343cb1e654900c2d4dedca5e938b /src/scope.c
parent9fb179ab999c3b98caabca09b30c409dc5dd3b3d (diff)
downloadek-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.c101
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;