diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-04-09 12:59:07 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-04-09 12:59:07 +0300 |
| commit | 451111dc51df69580d04c9965f70531f50e3d509 (patch) | |
| tree | 379a7123f2588f149021c896118ce0ded4f5a9cc /src/actualize.c | |
| parent | f86cb1e9ec6cb562d1d0ebf4b0fd7119296ff10d (diff) | |
| download | ek-451111dc51df69580d04c9965f70531f50e3d509.tar.gz ek-451111dc51df69580d04c9965f70531f50e3d509.zip | |
add initial ufcs checks
Diffstat (limited to 'src/actualize.c')
| -rw-r--r-- | src/actualize.c | 106 |
1 files changed, 72 insertions, 34 deletions
diff --git a/src/actualize.c b/src/actualize.c index dc9fe1d..7d30a0f 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -347,6 +347,8 @@ static void set_type(struct ast *node, struct type *type) node->t = clone_type_list(type); } +/* important to keep in mind that this does not maintain list state, must be + * done elsewhere */ static void replace_type(struct type *t, struct type *r) { /* free strings before they get overwritten */ @@ -836,11 +838,52 @@ static int actualize_macro_expand(struct act_state *state, } free(macro_expand_id(macro_expand)); - *macro_expand = *body; + replace_ast(macro_expand, body); /* actualize the new content */ return actualize(state, scope, macro_expand); } +static int simplify_refderef(struct act_state *state, struct scope *scope, struct ast *n) +{ + if (!is_unop(n)) + return 0; + + struct ast *e = unop_expr(n); + if (n->k == AST_REF && e->k == AST_DEREF) { + replace_ast(n, unop_expr(e)); + return simplify_refderef(state, scope, n); + } + + if (n->k == AST_DEREF && e->k == AST_REF) { + replace_ast(n, unop_expr(e)); + return simplify_refderef(state, scope, n); + } + + return 0; +} + +static int maybe_ufcs(struct act_state *state, struct scope *scope, struct ast *call) +{ + assert(call->k == AST_CALL); + struct ast *dot = call_expr(call); + if (dot->k != AST_DOT) + return 0; + + struct ast *expr = dot_expr(dot); + call_expr(call) = gen_fetch(dot_id(dot), clone_type(expr->t), dot->loc); + + /* hard core type */ + struct ast *ref = gen_unop(AST_REF, expr, dot->loc); + ref->t = tgen_ptr(clone_type(expr->t), dot->loc); + ref->scope = scope; + + if (simplify_refderef(state, scope, ref)) + return -1; + + ast_prepend(call_args(call), ref); + return 0; +} + static int actualize_call(struct act_state *state, struct scope *scope, struct ast *call) { @@ -861,6 +904,9 @@ static int actualize_call(struct act_state *state, return -1; } + if (maybe_ufcs(state, scope, call)) + return -1; + struct type *callable = expr->t; struct type *ptypes = callable_ptypes(callable); struct ast *arg = call_args(call); @@ -935,13 +981,16 @@ static int actualize_proc(struct act_state *state, /* actualize body */ new_state.cur_proc = proc; - if (actualize(&new_state, proc->scope, proc_body(proc))) + if (actualize(&new_state, proc->scope, proc_body(proc))) { + destroy_act_state(&new_state); return -1; + } if (!act_flags(&new_state, ACT_HAS_RETURN)) { if (!is_void(proc_rtype(proc))) { semantic_error(scope->fctx, proc, "no return with non-void return type"); + destroy_act_state(&new_state); return -1; } @@ -955,12 +1004,15 @@ static int actualize_proc(struct act_state *state, /* TODO: something more sophisticated than this */ semantic_warn(scope->fctx, proc, "unable to determine explicit return for all branches"); + destroy_act_state(&new_state); return -1; } warn_unused_labels(&new_state, scope); - if (undefined_gotos(&new_state, scope)) + if (undefined_gotos(&new_state, scope)) { + destroy_act_state(&new_state); return -1; + } /* if we're main, don't mangle the entry point */ char *id = proc_id(proc); @@ -968,6 +1020,7 @@ static int actualize_proc(struct act_state *state, ast_set_flags(proc, AST_FLAG_NOMANGLE); /* we have successfully actualized the procedure */ + destroy_act_state(&new_state); return 0; } @@ -1142,8 +1195,6 @@ static int actualize_tid(struct act_state *state, struct scope *scope, struct ty return 0; } - struct src_loc l = t->loc; - struct ast *def = file_scope_find_type(scope, t->id); if (!def) { type_error(scope->fctx, t, "no such type"); @@ -1200,6 +1251,7 @@ static int actualize_callable(struct act_state *state, struct scope *scope, stru static int actualize_i27(struct act_state *state, struct scope *scope, struct type *t) { + UNUSED(state); /* not much to do */ if (t->d) return 0; @@ -1207,7 +1259,7 @@ static int actualize_i27(struct act_state *state, struct scope *scope, struct ty struct ast *def = file_scope_find_type(scope, "i27"); if (!def) { error("missing definition of type 'i27'"); - return NULL; + return -1; } t->d = def; @@ -1216,6 +1268,7 @@ static int actualize_i27(struct act_state *state, struct scope *scope, struct ty static int actualize_i9(struct act_state *state, struct scope *scope, struct type *t) { + UNUSED(state); /* not much to do */ if (t->d) return 0; @@ -1223,7 +1276,7 @@ static int actualize_i9(struct act_state *state, struct scope *scope, struct typ struct ast *def = file_scope_find_type(scope, "i9"); if (!def) { error("missing definition of type 'i9'"); - return NULL; + return -1; } t->d = def; @@ -1232,6 +1285,7 @@ static int actualize_i9(struct act_state *state, struct scope *scope, struct typ static int actualize_bool(struct act_state *state, struct scope *scope, struct type *t) { + UNUSED(state); /* not much to do */ if (t->d) return 0; @@ -1239,7 +1293,7 @@ static int actualize_bool(struct act_state *state, struct scope *scope, struct t struct ast *def = file_scope_find_type(scope, "bool"); if (!def) { error("missing definition of type 'bool'"); - return NULL; + return -1; } t->d = def; @@ -1693,6 +1747,7 @@ static void actualize_goto_defer(struct ast *got, struct ast *label) static int actualize_goto(struct act_state *state, struct scope *scope, struct ast *node) { + UNUSED(scope); assert(node->k == AST_GOTO); push_goto(state, node); @@ -1726,6 +1781,7 @@ static void actualize_goto_defers(struct act_state *state, static int actualize_label(struct act_state *state, struct scope *scope, struct ast *node) { + UNUSED(scope); assert(node->k == AST_LABEL); struct ast *prev = find_label(state, label_id(node)); if (prev) { @@ -1769,12 +1825,18 @@ static int actualize_unop(struct act_state *state, set_type(node, ptr_base(type)); assert(node->t); + if (simplify_refderef(state, scope, node)) + return -1; + break; } case AST_REF: { /** @todo array pointer decay? */ node->t = tgen_ptr(clone_type(expr->t), node->loc); + if (simplify_refderef(state, scope, node)) + return -1; + break; } @@ -1881,6 +1943,7 @@ static int replace_type_id(struct ast *nodes, char *id, static int actualize_trait(struct act_state *state, struct scope *scope, struct ast *node) { + UNUSED(scope); assert(node->k == AST_TRAIT_DEF); foreach_node(n, trait_body(node)) { /* there's really only prodcedure body actualization left I @@ -1903,6 +1966,7 @@ static int actualize_trait(struct act_state *state, struct scope *scope, static int actualize_struct(struct act_state *state, struct scope *scope, struct ast *node) { + UNUSED(scope); assert(node->k == AST_STRUCT_DEF); foreach_node(n, struct_body(node)) { /* there's really only prodcedure body actualization left I @@ -1922,35 +1986,9 @@ static int actualize_struct(struct act_state *state, return 0; } -/* could maybe be renamed, but essentially dot in copper works as either - * -> or . in C, so allow structures or traits and single level pointers to - * structures or traits. */ -static int has_members(struct type *type) -{ - /* most likely */ - if (type->k == TYPE_STRUCT) - return 1; - - if (type->k == TYPE_TRAIT) - return 1; - - if (type->k == TYPE_CONSTRUCT) - return 1; - - return 0; -} - static int actualize_dot(struct act_state *state, struct scope *scope, struct ast *node) { - /* TODO: handle enums as well, idea is something like - * enum whatever {A_FLAG} - * ... - * whatever.A_FLAG - * - * possibly also if the expr is of type whatever then .A_FLAG just gets - * the corresponding constant? - **/ assert(node->k == AST_DOT); struct ast *expr = dot_expr(node); if (actualize(state, scope, expr)) |
