From d1440ea9923a24362c0b2e110b9ddf203aba8f41 Mon Sep 17 00:00:00 2001 From: Jan Klaas Kollhof Date: Tue, 19 Oct 2021 16:17:26 +0200 Subject: [PATCH] fix(func): avoid inlining self referenced funcs --- src/ir/func/init.test.fnk | 23 +++++++++++ src/ir/func/init.test.fnk.snap | 73 ++++++++++++++++++++++++++++++++++ src/js/func/init.fnk | 4 +- src/js/func/init.test.fnk | 11 +++++ src/js/func/init.test.fnk.snap | 18 +++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src/ir/func/init.test.fnk b/src/ir/func/init.test.fnk index 63b9f78..7a13826 100644 --- a/src/ir/func/init.test.fnk +++ b/src/ir/func/init.test.fnk @@ -112,6 +112,29 @@ describe 'func', fn: to_match_snapshot + it 'handles self ref', fn: + expect + fink2lir ' + foo = fn: + count = fn start: + _iterable_ fn: + [start + 1, count start + 1] + + count 0 + ' + to_match_snapshot + + expect + fink2lir ' + foo = fn: + count = fn start: + _iterable_ fn: + [start + 1, count start + 1] + + count 0 + ', {optimize: {refs: true, tails: true, unused: true}} + to_match_snapshot + describe 'recursive funcs', fn: it 'compiles recursive calls', fn: diff --git a/src/ir/func/init.test.fnk.snap b/src/ir/func/init.test.fnk.snap index baa6acc..1308ae3 100644 --- a/src/ir/func/init.test.fnk.snap +++ b/src/ir/func/init.test.fnk.snap @@ -355,6 +355,79 @@ rec_e fn exports_0: mod exports_1, drctvs_0, fn mod_0:" `; +exports[`func handles self ref 1`] = ` +" +rec_e fn exports_0: + id (fn args_0, ret_2: #fn + z (fn args_1, ret_1, count_0_0: #fn + lst_h args_1, fn start_0: + lst_t args_1, fn tail_0: + id _iterable_, fn callee_0: + lst_e fn cargs_0: + id (fn args_2, ret_0: #fn + lst_e fn lst_1: + id start_0, fn left_1: + int '1', fn right_1: + add left_1, right_1, fn item_1: + lst_a lst_1, item_1, fn lst_0: + id count_0_0, fn callee_1: + lst_e fn cargs_1: + id start_0, fn left_0: + int '1', fn right_0: + add left_0, right_0, fn arg_1: + lst_a cargs_1, arg_1, fn cargs_2: + af callee_1, cargs_2, fn item_0: + lst_a lst_0, item_0, fn result_2: + cc ret_0, result_2 + ), fn arg_0: + lst_a cargs_0, arg_0, fn cargs_3: + af callee_0, cargs_3, fn result_1: + cc ret_1, result_1 + ), fn count_0: + id count_0, fn callee_2: + lst_e fn cargs_4: + int '0', fn arg_2: + lst_a cargs_4, arg_2, fn cargs_5: + af callee_2, cargs_5, fn result_3: + cc ret_2, result_3 + ), fn foo_0: + str 'foo', fn key_0: + rec_s exports_0, key_0, foo_0, fn exports_1: + lst_e fn drctvs_0: + mod exports_1, drctvs_0, fn mod_0:" +`; + +exports[`func handles self ref 2`] = ` +" +rec_e fn exports_0: + id (fn args_0, ret_2: #fn + z (fn args_1, ret_1, count_0_0: #fn + tpl_i args_1, 0, fn start_0: + id (fn args_2, ret_0: #fn + int '1', fn right_1: + add start_0, right_1, fn item_1: + int '1', fn right_0: + add start_0, right_0, fn arg_1: + tpl arg_1, fn cargs_2: + af count_0_0, cargs_2, fn item_0: + tpl item_1, item_0, fn result_2: + cc ret_0, result_2 + ), fn arg_0: + tpl arg_0, fn cargs_3: + af _iterable_, cargs_3, fn result_1: + cc ret_1, result_1 + ), fn count_0: + int '0', fn arg_2: + tpl arg_2, fn cargs_5: + af count_0, cargs_5, fn result_3: + cc ret_2, result_3 + ), fn foo_0: + str 'foo', fn key_0: + rec_s exports_0, key_0, foo_0, fn exports_1: + tpl, fn drctvs_0: + mod exports_1, drctvs_0, fn mod_0:" +`; + exports[`func handles self-ref scoping 1`] = ` " rec_e fn exports_0: diff --git a/src/js/func/init.fnk b/src/js/func/init.fnk index e47962f..7ca9950 100644 --- a/src/js/func/init.fnk +++ b/src/js/func/init.fnk @@ -84,7 +84,8 @@ transform_normal_fn = fn expr, ctx: self_ctx = set_js ret_id, ret, ctx body_ctx = match self_id: - false: self_ctx + false: + self_ctx else: pipe self_ctx: # set recursive calls to use res_id @@ -92,6 +93,7 @@ transform_normal_fn = fn expr, ctx: set_js self_id, (ident res_id), ? # make sure calls to self_id always use res_id update_value self_id, {ignore_refs: true}, ? + update_value res_id, {inline: false}, ? [args, block, fn_ctx] = pipe body_ctx: split_args_body fn_block, args_id, ? diff --git a/src/js/func/init.test.fnk b/src/js/func/init.test.fnk index 32120c6..875da09 100644 --- a/src/js/func/init.test.fnk +++ b/src/js/func/init.test.fnk @@ -145,6 +145,17 @@ describe 'recursive functions', fn: ' to_match_snapshot + expect + fink2js ' + foo = fn: + count = fn start: + _iterable_ fn: + [start + 1, count start + 1] + + count 0 + ' + to_match_snapshot + it 'compiles to while loop', fn: expect diff --git a/src/js/func/init.test.fnk.snap b/src/js/func/init.test.fnk.snap index 814567e..aad6a3d 100644 --- a/src/js/func/init.test.fnk.snap +++ b/src/js/func/init.test.fnk.snap @@ -211,3 +211,21 @@ exports[`recursive functions compiles with self reference 1`] = ` export const foo = foo_0;" `; + +exports[`recursive functions compiles with self reference 2`] = ` +"const foo_0 = () => { + const count_0 = start_0 => { + const result_1 = _iterable_(() => { + const item_0 = count_0(start_0 + 1); + return [start_0 + 1, item_0]; + }); + + return result_1; + }; + + const result_3 = count_0(0); + return result_3; +}; + +export const foo = foo_0;" +`;