From 17c7dbd9cec96862384c4323a0e36eb0558b580d Mon Sep 17 00:00:00 2001 From: Kimplul Date: Mon, 17 Mar 2025 21:49:25 +0200 Subject: fix some total moves --- examples/fib.fwd | 8 +++----- include/fwd/ast.h | 5 +++++ src/lower.c | 9 +++++++++ src/move.c | 32 +++++++++++++++++++++++++++----- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/examples/fib.fwd b/examples/fib.fwd index 9bc5474..7084b9d 100644 --- a/examples/fib.fwd +++ b/examples/fib.fwd @@ -5,13 +5,11 @@ fib(int n, (int) res) { - fwd_copy(n) => int n1, int n2; - if n1 < 2 { + if n < 2 { res(1); } else { - fwd_copy(n2) => int n3, int n4; - fib(n3 - 1) => int f1; - fib(n4 - 2) => int f2; + fib(n - 1) => int f1; + fib(n - 2) => int f2; res(f1 + f2); } } diff --git a/include/fwd/ast.h b/include/fwd/ast.h index 5f2b7cb..a253901 100644 --- a/include/fwd/ast.h +++ b/include/fwd/ast.h @@ -5,6 +5,7 @@ #define AST_H #include +#include #include #include @@ -280,6 +281,10 @@ static inline bool is_trivially_copyable(struct type *type) /** @todo primitive types */ return true; + case TYPE_ID: + /* very special, bad bad bad */ + return strcmp(type->id, "int") == 0; + default: return false; } diff --git a/src/lower.c b/src/lower.c index 5578319..b683e0b 100644 --- a/src/lower.c +++ b/src/lower.c @@ -309,6 +309,12 @@ static int lower_mark_moved(struct state *state, struct ast *moves) if (move->k != AST_ID) continue; + if (is_trivially_copyable(move->t)) + continue; + + if (is_callable(move->t)) + continue; + printf("%s_owned = false;\n", id_str(move)); indent(state); } @@ -450,6 +456,9 @@ static int lower_block_vars(struct state *state, struct ast *block) if (is_trivially_copyable(def->t)) continue; + if (is_callable(def->t)) + continue; + if (!populated) { indent(state); printf("[[maybe_unused]] bool %s_owned = true", diff --git a/src/move.c b/src/move.c index a87d6dd..6ed687b 100644 --- a/src/move.c +++ b/src/move.c @@ -234,6 +234,9 @@ static int total_check_single(struct state *state, struct scope *scope) if (is_trivially_copyable(def->t)) continue; + if (is_callable(def->t)) + continue; + struct ast_pair *prev = find_move(state, def); if (prev) continue; @@ -294,10 +297,27 @@ static int mvcheck_call(struct state *state, struct ast *node) if (!args) return 0; + /* get all 'normal' parameters moved */ + foreach_node(arg, call_args(node)) { + if (arg->k == AST_CLOSURE) + continue; + + if (mvcheck(state, arg)) + return -1; + } + + /* check if there are any arguments that might not be moved if function + * returns immediately */ + if (!call_err(node) && total_check_proc(state, node->scope)) + semantic_info(node->scope, node, "in implicit error branch"); + + /* check into closures */ int ret = 0; struct state group_state = create_state(state); - foreach_node(arg, call_args(node)) { + if (arg->k != AST_CLOSURE) + continue; + struct state arg_state = create_state(state); ret = mvcheck(&arg_state, arg); @@ -324,10 +344,6 @@ static int mvcheck_call(struct state *state, struct ast *node) push_up(&err_state); destroy_state(&err_state); } - else if (!ret) { - if (total_check_proc(state, node->scope)) - semantic_info(node->scope, node, "in implicit error branch"); - } destroy_state(&group_state); return ret; @@ -507,6 +523,12 @@ static int mvcheck_own(struct state *state, struct ast *node) struct ast *def = file_scope_find_symbol(node->scope, own_id(node)); assert(def); + if (is_callable(def->t)) { + semantic_error(node->scope, node, + "ownership of callable cannot be checked"); + return -1; + } + struct rm_move prev = remove_move(state, def); int ret = mvcheck(state, own_body(node)); -- cgit v1.2.3