diff options
-rw-r--r-- | examples/fib.fwd | 8 | ||||
-rw-r--r-- | include/fwd/ast.h | 5 | ||||
-rw-r--r-- | src/lower.c | 9 | ||||
-rw-r--r-- | 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 <stddef.h> +#include <string.h> #include <assert.h> #include <stdbool.h> @@ -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", @@ -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)); |