diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-08-14 18:51:28 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-08-14 18:51:28 +0300 |
| commit | 852ff838af56ef3668ff94c27b0140869dcb7359 (patch) | |
| tree | fbb51f25484832aeb4acc24ca0e9fb16a0831b7d /src | |
| parent | 085817c69d145400eac84e09704f48ede2bece68 (diff) | |
| download | ek-852ff838af56ef3668ff94c27b0140869dcb7359.tar.gz ek-852ff838af56ef3668ff94c27b0140869dcb7359.zip | |
allow adding traits to pointers
+ Should be enough to fairly easily use pointers in standard containers.
Note that this just uses the pointer value itself, and doesn't care
about the underlying type at all. So for example a sorted vector of
pointers is sorted by the address, not by some comparison function
that the underlying type may have defined. For that you will need a
wrapper struct or something.
Diffstat (limited to 'src')
| -rw-r--r-- | src/actualize.c | 62 | ||||
| -rw-r--r-- | src/debug.c | 25 |
2 files changed, 76 insertions, 11 deletions
diff --git a/src/actualize.c b/src/actualize.c index 5a642a7..2cf4c13 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -462,6 +462,8 @@ static struct ast *analyze_type_expand(struct scope *scope, return NULL; } + n->t = trait->t; + struct ast *body = trait_body(trait); body = clone_ast(body); @@ -553,6 +555,13 @@ int types_match(struct type *a, struct type *b) if (a->k == TYPE_STRUCT) return structs_match(a, b); + if (a->k == TYPE_PTR && b->k == TYPE_PTR) { + if (is_void(ptr_base(a))) + return 1; + else if (is_void(ptr_base(b))) + return 1; + } + if (a->k == TYPE_PTR) return types_match(ptr_base(a), ptr_base(b)); @@ -628,8 +637,10 @@ static int implements(struct type *trait, struct type *type) assert(type->d); struct ast *def = type->d; + assert(def->k == AST_STRUCT_DEF); + struct ast *body = struct_body(def); - foreach_node(n, def) { + foreach_node(n, body) { if (n->k != AST_TYPE_EXPAND) continue; @@ -915,6 +926,9 @@ static int maybe_ufcs(struct act_state *state, struct scope *scope, /* is ufcs expects reference to member, try to take address */ ref = gen_unop(AST_REF, expr, dot->loc); ref->t = tgen_ptr(clone_type(expr->t), dot->loc); + if (actualize_type(state, scope, ref->t)) + return -1; + ref->scope = scope; } else { @@ -1302,6 +1316,12 @@ static int actualize_ptr(struct act_state *state, struct scope *scope, struct type *t) { assert(ptr_base(t)); + t->d = actualized_file_scope_find_type(state, scope, "ptr"); + if (!t->d) { + type_error(scope->fctx, t, "no pointer type"); + return -1; + } + if (actualize_type(state, scope, ptr_base(t))) return -1; @@ -1667,10 +1687,10 @@ static int actualize_return(struct act_state *state, struct scope *scope, assert(state->cur_proc); struct ast *cur_proc = state->cur_proc; - struct type *rtype = cur_proc->t; - if (!types_match(node->t, callable_rtype(rtype))) { - type_mismatch(scope, "return type mismatch", node, rtype, - node->t); + struct type *rtype = callable_rtype(cur_proc->t); + if (!types_match(node->t, rtype)) { + type_mismatch(scope, "return type mismatch", node, + rtype, node->t); return -1; } @@ -1827,6 +1847,9 @@ static int actualize_unop(struct act_state *state, case AST_REF: { /** @todo array pointer decay? */ node->t = tgen_ptr(clone_type(expr->t), node->loc); + if (actualize_type(state, scope, node->t)) + return -1; + if (simplify_refderef(state, scope, node)) return -1; @@ -2070,15 +2093,20 @@ static int actualize_struct(struct act_state *state, ast_set_flags(node, AST_FLAG_GENERIC); /* do type setting first to make sure body checking works */ - char *id = strdup(struct_id(node)); + char *id = struct_id(node); if (same_id(id, "i27")) - node->t = tgen_primitive(TYPE_I27, id, node, node->loc); + node->t = tgen_primitive(TYPE_I27, strdup(id), node, node->loc); else if (same_id(id, "i9")) - node->t = tgen_primitive(TYPE_I9, id, node, node->loc); + node->t = tgen_primitive(TYPE_I9, strdup(id), node, node->loc); else if (same_id(id, "bool")) - node->t = tgen_primitive(TYPE_BOOL, id, node, node->loc); + node->t = tgen_primitive(TYPE_BOOL, strdup(id), node, node->loc); + else if (same_id(id, "ptr")) { + node->t = tgen_ptr(void_type(), node->loc); + /* we know we're the definition for pointers */ + node->t->d = node; + } else - node->t = tgen_struct(id, node, node->loc); + node->t = tgen_struct(strdup(id), node, node->loc); /* iterate over types and make aliases to them */ struct type *types = NULL; @@ -2111,6 +2139,16 @@ static int actualize_struct(struct act_state *state, if (n->k != AST_TYPE_EXPAND) continue; + /** @todo when I eventually implement continuing structure + * definitions I might add the primitive types by default to + * structs, that way we don't need this check or the above type + * table */ + if (n->k == AST_VAR_DEF && node->t->k != TYPE_STRUCT) { + semantic_error(scope->fctx, n, + "variables not allowed in primitive struct"); + return -1; + } + if (has_trait(struct_body(node), type_expand_id(n))) { n->k = AST_EMPTY; continue; @@ -2224,6 +2262,7 @@ static int actualize_dot(struct act_state *state, case TYPE_I9: case TYPE_I27: case TYPE_BOOL: + case TYPE_PTR: case TYPE_TRAIT: case TYPE_STRUCT: def = type->d; break; default: { @@ -2236,7 +2275,8 @@ static int actualize_dot(struct act_state *state, } } - struct ast *exists = actualized_scope_find_symbol(state, def->scope, + struct ast *exists = actualized_scope_find_symbol(state, + def->scope, id); if (exists) { assert(exists->t); diff --git a/src/debug.c b/src/debug.c index 47e53f2..92d85d2 100644 --- a/src/debug.c +++ b/src/debug.c @@ -218,6 +218,22 @@ void internal_warn(const char *fmt, ...) va_end(args); } +static void _type_str(FILE *fp, struct type *type); + +static void _type_list_str(FILE *fp, struct type *types) +{ + if (!types) + return; + + _type_str(fp, types); + + types = types->n; + foreach_type(t, types) { + fprintf(fp, ", "); + _type_str(fp, t); + } +} + /** * Workhorse for type_str(). * @@ -263,6 +279,15 @@ static void _type_str(FILE *fp, struct type *type) break; } + case TYPE_CALLABLE: { + fputc('(', fp); + _type_list_str(fp, callable_ptypes(type)); + fprintf(fp, " => "); + _type_str(fp, callable_rtype(type)); + fputc(')', fp); + break; + } + default: if (is_primitive(type)) fprintf(fp, "%s", primitive_str(type)); |
