From 12d33698b3d4ab1a7149605e2d19b3602f9a00b2 Mon Sep 17 00:00:00 2001 From: Jan Klaas Kollhof Date: Sun, 19 Sep 2021 17:49:58 +0200 Subject: [PATCH] fix: add missing support for member expr in records --- src/generate.fnk | 7 +- src/generate.test.fnk | 4 +- src/generate.test.fnk.snap | 6 +- src/ir/assignment/init.fnk | 6 +- src/ir/conditionals/match.fnk | 9 +- src/ir/conditionals/match.test.fnk | 3 +- src/ir/conditionals/match.test.fnk.snap | 287 ++++++++++++++--------- src/ir/context.fnk | 2 - src/ir/func/init.test.fnk | 4 +- src/ir/func/init.test.fnk.snap | 290 ++++++++++++------------ src/ir/literals/record.fnk | 18 ++ src/ir/literals/record.test.fnk | 6 +- src/ir/literals/record.test.fnk.snap | 177 ++++++++------- src/ir/module/init.test.fnk | 3 +- src/js/async/init.test.fnk | 15 +- src/js/async/init.test.fnk.snap | 25 +- src/js/conditionals/match.test.fnk | 13 +- src/js/conditionals/match.test.fnk.snap | 151 +++++------- src/js/init.fnk | 2 - src/js/literals/record.fnk | 17 +- src/js/literals/record.test.fnk | 6 +- src/js/literals/record.test.fnk.snap | 121 ++++------ src/js/module/init.fnk | 20 +- src/js/module/init.test.fnk | 17 +- src/js/module/init.test.fnk.snap | 8 +- src/js/transform.fnk | 15 +- 26 files changed, 638 insertions(+), 594 deletions(-) diff --git a/src/generate.fnk b/src/generate.fnk index 2f171d8..e83d061 100644 --- a/src/generate.fnk +++ b/src/generate.fnk @@ -12,10 +12,15 @@ babel_traverse = import '@babel/traverse' {transform_async} = import './js/async/init.fnk' +try_catch_ = fn func: + r = func _ + [false, r] + + transform_file = fn fink_ast, code, filename, options: ctx = init_ctx code, filename, options - [error, [js_ast]=[]] = try_catch fn: + [error, [js_ast]=[]] = try_catch_ fn: [lir] = transform fink_ast, 'mod', ctx [olir] = optimize lir, options {js} = transform_ir olir, options diff --git a/src/generate.test.fnk b/src/generate.test.fnk index 17855e9..c73e3a5 100644 --- a/src/generate.test.fnk +++ b/src/generate.test.fnk @@ -1,4 +1,4 @@ -{only, skip, describe, it, expect, to_equal, to_match_snapshot} = import '@fink/jest/test.fnk' +{skip, describe, it, expect, to_equal, to_match_snapshot} = import '@fink/jest/test.fnk' {slice} = import '@fink/std-lib/str.fnk' {generate} = import './generate.fnk' @@ -35,7 +35,7 @@ describe 'module types', fn: -only.describe 'source maps', fn: +describe 'source maps', fn: code = " foo = 12345 bar = 'foo' diff --git a/src/generate.test.fnk.snap b/src/generate.test.fnk.snap index 13b5698..7d1216a 100644 --- a/src/generate.test.fnk.snap +++ b/src/generate.test.fnk.snap @@ -19,7 +19,11 @@ const { const { ˆif: if_0 -} = require(\\"es6-module\\");" +} = require(\\"es6-module\\"); + +exports.ˆdefault = ni_0; +exports.ˆcase = ni_0; +exports.shrub = ni_0;" `; exports[`module types compiles to mjs 1`] = ` diff --git a/src/ir/assignment/init.fnk b/src/ir/assignment/init.fnk index 64e0e9f..05ce781 100644 --- a/src/ir/assignment/init.fnk +++ b/src/ir/assignment/init.fnk @@ -2,7 +2,7 @@ {add, any, unique_ident} = import '../context.fnk' {transform} = import '../transform.fnk' - +{members_as_rec} = import '../literals/record.fnk' bind = fn {value: src_id}, ctx: @@ -85,6 +85,10 @@ transform_dr = fn [expr=false, ...exprs], rec_id, ctx, keys=[], prev=[], fallbac [{...expr, right: left}, ...exprs] rec_id, dl_ctx, keys, [...prev, ...flbk], flbk_id + {left.type: 'member'}: + {exprs: rx} = members_as_rec expr.left, expr.right + transform_dr [...rx, ...exprs], rec_id, ctx, keys, prev, fallback + {right.type: ? in ['ident', 'empty']}: [key, key_id, val_id, next_ctx] = get_key_val expr, ctx [val, end_ctx] = rec_get rec_id, key_id, val_id, {loc: expr.loc}, next_ctx, fallback diff --git a/src/ir/conditionals/match.fnk b/src/ir/conditionals/match.fnk index 4e01cca..4a3149b 100644 --- a/src/ir/conditionals/match.fnk +++ b/src/ir/conditionals/match.fnk @@ -1,7 +1,7 @@ {reverse} = import '@fink/std-lib/iter.fnk' -{transform_key} = import '../literals/record.fnk' +{transform_key, members_as_rec} = import '../literals/record.fnk' {transform} = import '../transform.fnk' {unique_ident} = import '../context.fnk' @@ -130,6 +130,10 @@ match_rec = fn [expr=false, ...rest], rec_id, true_cont, true_id, else_ids, ret_ [x, y, z] = match_expr val_id, expr.right, rest_cont, rest_cont_id, else_ids, ret_id, rest_ctx [[['rec_d', [rec_id, ...keys], [val_id], {loc: expr.loc}], ...x], y, z] + {type: 'rec:kv', left.type: 'member'}: + {exprs} = members_as_rec expr.left, expr.right + match_rec [...exprs, ...rest], rec_id, true_cont, true_id, else_ids, ret_id, ctx, keys + {type: 'rec:kv'}: [val_id, key_ctx] = unique_ident 'itm', ctx [key, key_id, next_ctx] = transform_key expr.left, key_ctx @@ -142,7 +146,7 @@ match_rec = fn [expr=false, ...rest], rec_id, true_cont, true_id, else_ids, ret_ else: expr.right [x, y, z] = match_expr val_id, val_expr, rest_cont, rest_cont_id, else_ids, ret_id, rest_ctx - [[...key, ['rec_g', [rec_id, key_id], [val_id], {loc: expr.loc}], ...x], y, z] + [[...key, ['rec_go', [rec_id, key_id], [val_id], {loc: expr.loc}], ...x], y, z] @@ -157,6 +161,7 @@ match_expr = fn val_id, expr, true_cont, true_cont_id, else_ids, ret_id, ctx: {type: 'rec'}: match_rec expr.exprs, val_id, true_cont, true_cont_id, else_ids, ret_id, ctx + {type: 'partial'}: match_any val_id, true_cont, true_cont_id, else_ids, {loc: expr.loc}, ctx diff --git a/src/ir/conditionals/match.test.fnk b/src/ir/conditionals/match.test.fnk index a8e5e65..02066ea 100644 --- a/src/ir/conditionals/match.test.fnk +++ b/src/ir/conditionals/match.test.fnk @@ -164,6 +164,7 @@ describe 'match records', fn: {foo: 4, ni: {na, nu}}: spam + ni {foo: 1, foo: {bar: 'spam'}, shrub: {na: 'nu'}}: ni {ni: {len: 1}, na: {len: 1}}: na + {ni: [na, 123]}: na " to_match_snapshot @@ -188,7 +189,7 @@ describe 'match records', fn: to_match_snapshot - skip.it 'matches member expr keys', fn: + it 'matches member expr keys', fn: expect fink2lir ' match foo: diff --git a/src/ir/conditionals/match.test.fnk.snap b/src/ir/conditionals/match.test.fnk.snap index ddc14d2..5adc07d 100644 --- a/src/ir/conditionals/match.test.fnk.snap +++ b/src/ir/conditionals/match.test.fnk.snap @@ -615,13 +615,13 @@ rec >> exports_0: cn ret_0: = shrub >> value_0: = a >> key_0: - rec_g value_0, key_0 >> itm_0: + rec_go value_0, key_0 >> itm_0: str 'b' >> key_1 - rec_g itm_0, key_1 >> itm_1: + rec_go itm_0, key_1 >> itm_1: = b >> val_1: == itm_1, val_1 >> cond_1: str 'c' >> key_2 - rec_g itm_0, key_2 >> itm_2: + rec_go itm_0, key_2 >> itm_2: = c >> val_0: cn: == itm_2, val_0 >> cond_0: @@ -638,109 +638,180 @@ rec >> exports_0: mod exports_0, drctvs_0 >> mod_0:" `; +exports[`match records matches member expr keys 1`] = ` +" +rec >> exports_0: + cn ret_0: + = foo >> value_0: + str 'foo' >> key_0 + rec_go value_0, key_0 >> itm_0: + str 'bar' >> key_1 + rec_go itm_0, key_1 >> itm_1: + str 'spam' >> key_2 + rec_go itm_1, key_2 >> itm_2: + = ham >> val_0: + == itm_2, val_0 >> cond_0: + cn: + = spam >> result_0: + cc ret_0, result_0 + >> match_res_0: + cif cond_0, match_res_0 + >> match_0: + ac match_0 >> mex_0: + lst >> drctvs_0: + mod exports_0, drctvs_0 >> mod_0:" +`; + +exports[`match records matches member expr keys 2`] = ` +" +rec >> exports_0: + cn ret_0: + = foo >> value_0: + str 'foo' >> key_0 + rec_go value_0, key_0 >> itm_0: + str 'bar' >> key_1 + rec_go itm_0, key_1 >> itm_1: + str 'spam' >> key_2 + rec_go itm_1, key_2 >> itm_2: + str 'ham' >> key_3 + rec_go itm_2, key_3 >> itm_3: + str 'ni' >> key_4 + rec_go itm_3, key_4 >> itm_4: + = nu >> val_0: + == itm_4, val_0 >> cond_0: + cn: + = spam >> result_0: + cc ret_0, result_0 + >> match_res_0: + cif cond_0, match_res_0 + >> match_0: + ac match_0 >> mex_0: + lst >> drctvs_0: + mod exports_0, drctvs_0 >> mod_0:" +`; + exports[`match records matches props 1`] = ` " rec >> exports_0: cn ret_0: = shrub >> value_0: str 'ni' >> key_0 - rec_g value_0, key_0 >> itm_0: - str 'len' >> key_3 - rec_g itm_0, key_3 >> itm_3: - int 1 >> val_1: - cn: - == itm_3, val_1 >> cond_1: - str 'na' >> key_1 - rec_g value_0, key_1 >> itm_1: - str 'len' >> key_2 - rec_g itm_1, key_2 >> itm_2: - int 1 >> val_0: - cn: - == itm_2, val_0 >> cond_0: - cn: - = na >> result_0: - cc ret_0, result_0 - >> match_res_0: - cif cond_0, match_res_0 - >> match_1: - cif cond_1, match_1 - >> match_2: - str 'foo' >> key_4 - rec_g value_0, key_4 >> itm_4: - int 1 >> val_4: + rec_go value_0, key_0 >> itm_0: + lst_h itm_0 >> itm_1: + = na >> val_1: + cn: + == itm_1, val_1 >> cond_1: + lst_t itm_0 >> tail_0: + lst_h tail_0 >> itm_2: + int 123 >> val_0: cn: - == itm_4, val_4 >> cond_4: - str 'foo' >> key_5 - rec_g value_0, key_5 >> itm_5: - str 'bar' >> key_8 - rec_g itm_5, key_8 >> itm_8: - str 'spam' >> str_1 - strt str_1 >> val_3: + == itm_2, val_0 >> cond_0: + cn: + = na >> result_0: + cc ret_0, result_0 + >> match_res_0: + cif cond_0, match_res_0 + >> match_1: + cif cond_1, match_1 + >> match_2: + str 'ni' >> key_1 + rec_go value_0, key_1 >> itm_3: + str 'len' >> key_4 + rec_go itm_3, key_4 >> itm_6: + int 1 >> val_3: + cn: + == itm_6, val_3 >> cond_3: + str 'na' >> key_2 + rec_go value_0, key_2 >> itm_4: + str 'len' >> key_3 + rec_go itm_4, key_3 >> itm_5: + int 1 >> val_2: cn: - == itm_8, val_3 >> cond_3: - str 'shrub' >> key_6 - rec_g value_0, key_6 >> itm_6: - str 'na' >> key_7 - rec_g itm_6, key_7 >> itm_7: - str 'nu' >> str_0 - strt str_0 >> val_2: - cn: - == itm_7, val_2 >> cond_2: - cn: - = ni >> result_1: - cc ret_0, result_1 - >> match_res_1: - cif cond_2, match_res_1, match_2 - >> match_3: - cif cond_3, match_3, match_2 - >> match_4: - cif cond_4, match_4, match_2 - >> match_5: - str 'foo' >> key_9 - rec_g value_0, key_9 >> itm_9: - int 4 >> val_7: - cn: - == itm_9, val_7 >> cond_7: - str 'ni' >> key_10 - rec_g value_0, key_10 >> itm_10: - str 'na' >> key_11 - rec_g itm_10, key_11 >> itm_11: - = na >> val_6: - cn: - == itm_11, val_6 >> cond_6: - str 'nu' >> key_12 - rec_g itm_10, key_12 >> itm_12: - = nu >> val_5: + == itm_5, val_2 >> cond_2: + cn: + = na >> result_1: + cc ret_0, result_1 + >> match_res_1: + cif cond_2, match_res_1, match_2 + >> match_3: + cif cond_3, match_3, match_2 + >> match_4: + str 'foo' >> key_5 + rec_go value_0, key_5 >> itm_7: + int 1 >> val_6: + cn: + == itm_7, val_6 >> cond_6: + str 'foo' >> key_6 + rec_go value_0, key_6 >> itm_8: + str 'bar' >> key_9 + rec_go itm_8, key_9 >> itm_11: + str 'spam' >> str_1 + strt str_1 >> val_5: + cn: + == itm_11, val_5 >> cond_5: + str 'shrub' >> key_7 + rec_go value_0, key_7 >> itm_9: + str 'na' >> key_8 + rec_go itm_9, key_8 >> itm_10: + str 'nu' >> str_0 + strt str_0 >> val_4: + cn: + == itm_10, val_4 >> cond_4: + cn: + = ni >> result_2: + cc ret_0, result_2 + >> match_res_2: + cif cond_4, match_res_2, match_4 + >> match_5: + cif cond_5, match_5, match_4 + >> match_6: + cif cond_6, match_6, match_4 + >> match_7: + str 'foo' >> key_10 + rec_go value_0, key_10 >> itm_12: + int 4 >> val_9: + cn: + == itm_12, val_9 >> cond_9: + str 'ni' >> key_11 + rec_go value_0, key_11 >> itm_13: + str 'na' >> key_12 + rec_go itm_13, key_12 >> itm_14: + = na >> val_8: cn: - == itm_12, val_5 >> cond_5: - cn: - = spam >> left_0: - = ni >> right_0: - + left_0, right_0 >> result_2: - cc ret_0, result_2 - >> match_res_2: - cif cond_5, match_res_2, match_5 - >> match_6: - cif cond_6, match_6, match_5 - >> match_7: - cif cond_7, match_7, match_5 - >> match_8: - str 'foo' >> key_13 - rec_g value_0, key_13 >> itm_13: - = foo >> val_9: - == itm_13, val_9 >> cond_9: - str 'bar' >> key_14 - rec_g value_0, key_14 >> itm_14: - = bar >> val_8: - cn: - == itm_14, val_8 >> cond_8: - cn: - = ni >> result_3: - cc ret_0, result_3 - >> match_res_3: - cif cond_8, match_res_3, match_8 - >> match_9: - cif cond_9, match_9, match_8 + == itm_14, val_8 >> cond_8: + str 'nu' >> key_13 + rec_go itm_13, key_13 >> itm_15: + = nu >> val_7: + cn: + == itm_15, val_7 >> cond_7: + cn: + = spam >> left_0: + = ni >> right_0: + + left_0, right_0 >> result_3: + cc ret_0, result_3 + >> match_res_3: + cif cond_7, match_res_3, match_7 + >> match_8: + cif cond_8, match_8, match_7 + >> match_9: + cif cond_9, match_9, match_7 + >> match_10: + str 'foo' >> key_14 + rec_go value_0, key_14 >> itm_16: + = foo >> val_11: + == itm_16, val_11 >> cond_11: + str 'bar' >> key_15 + rec_go value_0, key_15 >> itm_17: + = bar >> val_10: + cn: + == itm_17, val_10 >> cond_10: + cn: + = ni >> result_4: + cc ret_0, result_4 + >> match_res_4: + cif cond_10, match_res_4, match_10 + >> match_11: + cif cond_11, match_11, match_10 >> match_0: ac match_0 >> mex_0: lst >> drctvs_0: @@ -753,14 +824,14 @@ rec >> exports_0: cn ret_0: = shrub >> value_0: = foo >> key_0: - rec_g value_0, key_0 >> itm_0: + rec_go value_0, key_0 >> itm_0: rec_d value_0, key_0 >> spread_0: str 'bar' >> key_1 - rec_g spread_0, key_1 >> itm_1: + rec_go spread_0, key_1 >> itm_1: = bar >> val_1: == itm_1, val_1 >> cond_1: str 'spam' >> key_2 - rec_g spread_0, key_2 >> itm_2: + rec_go spread_0, key_2 >> itm_2: = spam >> val_0: cn: == itm_2, val_0 >> cond_0: @@ -783,7 +854,7 @@ rec >> exports_0: cn ret_0: = foo >> value_0: str 'spam' >> key_0 - rec_g value_0, key_0 >> itm_0: + rec_go value_0, key_0 >> itm_0: cn: isv itm_0 >> cond_0: cn: @@ -793,7 +864,7 @@ rec >> exports_0: cif cond_0, match_res_0 >> match_1: str 'spam' >> key_1 - rec_g value_0, key_1 >> itm_1: + rec_go value_0, key_1 >> itm_1: = spam >> val_1: cn: == itm_1, val_1 >> cond_2: @@ -813,7 +884,7 @@ rec >> exports_0: cif cond_2, match_2, match_1 >> match_3: str 'spam' >> key_2 - rec_g value_0, key_2 >> itm_2: + rec_go value_0, key_2 >> itm_2: = spam >> val_3: cn: == itm_2, val_3 >> cond_4: @@ -834,7 +905,7 @@ rec >> exports_0: cif cond_4, match_4, match_3 >> match_5: str 'spam' >> key_3 - rec_g value_0, key_3 >> itm_3: + rec_go value_0, key_3 >> itm_3: = is_foo >> callee_1: lst >> cargs_2: = itm_3 >> arg_1: @@ -849,7 +920,7 @@ rec >> exports_0: cif cond_5, match_res_3, match_5 >> match_6: str 'spam' >> key_4 - rec_g value_0, key_4 >> itm_4: + rec_go value_0, key_4 >> itm_4: = itm_4 >> left_1: str 'is_foo' >> key_5 rec_g left_1, key_5 >> callee_2: @@ -864,7 +935,7 @@ rec >> exports_0: cif cond_6, match_res_4, match_6 >> match_7: str 'spam' >> key_6 - rec_g value_0, key_6 >> itm_5: + rec_go value_0, key_6 >> itm_5: = itm_5 >> callee_3: lst >> cargs_5: af callee_3, cargs_5 >> val_6: @@ -877,7 +948,7 @@ rec >> exports_0: cif cond_7, match_res_5, match_7 >> match_8: str 'spam' >> key_7 - rec_g value_0, key_7 >> itm_6: + rec_go value_0, key_7 >> itm_6: = itm_6 >> left_2: int 123 >> right_1: > left_2, right_1 >> val_7: @@ -890,7 +961,7 @@ rec >> exports_0: cif cond_8, match_res_6, match_8 >> match_9: str 'spam' >> key_8 - rec_g value_0, key_8 >> itm_7: + rec_go value_0, key_8 >> itm_7: = itm_7 >> right_2: not right_2 >> val_8: == true, val_8 >> cond_9: diff --git a/src/ir/context.fnk b/src/ir/context.fnk index 869035a..2720a4b 100644 --- a/src/ir/context.fnk +++ b/src/ir/context.fnk @@ -77,7 +77,6 @@ dec_refs = fn [id=false, ...exprs], ctx: - init_refs = fn [id=false, ...rest], ctx: match id: false: ctx @@ -85,7 +84,6 @@ init_refs = fn [id=false, ...rest], ctx: - is_unused = fn id, ctx: {refs} = get_value id, ctx # TODO 0 == get_refs id, ctx diff --git a/src/ir/func/init.test.fnk b/src/ir/func/init.test.fnk index af6ad3b..46b031f 100644 --- a/src/ir/func/init.test.fnk +++ b/src/ir/func/init.test.fnk @@ -1,4 +1,4 @@ -{only, describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' +{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' {fink2lir} = import '../../testing/generate.fnk' @@ -97,7 +97,7 @@ describe 'func', fn: to_match_snapshot - only.it 'eliminates tail calls', fn: + it 'eliminates tail calls', fn: expect fink2lir ' fun = fn a, b: diff --git a/src/ir/func/init.test.fnk.snap b/src/ir/func/init.test.fnk.snap index 808b676..cdb39c2 100644 --- a/src/ir/func/init.test.fnk.snap +++ b/src/ir/func/init.test.fnk.snap @@ -4,12 +4,12 @@ exports[`func compiles 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> a_0: - tpt args_0 >> tail_0: - tph tail_0 >> b_0: - tpt tail_0 >> tail_1: - tph tail_1 >> d_0: - tpt tail_1 >> tail_2: + lst_h args_0 >> a_0: + lst_t args_0 >> tail_0: + lst_h tail_0 >> b_0: + lst_t tail_0 >> tail_1: + lst_h tail_1 >> d_0: + lst_t tail_1 >> tail_2: = a_0 >> left_1: = b_0 >> right_0: + left_1, right_0 >> left_0: @@ -17,26 +17,26 @@ rec >> exports_0: + left_0, right_1 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: fn args_1, ret_1: - tph args_1 >> foo_0: - tpt args_1 >> tail_3: + lst_h args_1 >> foo_0: + lst_t args_1 >> tail_3: fn args_2, ret_2: - tph args_2 >> bar_0: - tpt args_2 >> tail_4: + lst_h args_2 >> bar_0: + lst_t args_2 >> tail_4: = foo_0 >> callee_0: - tpl >> tpl_0: - = bar_0 >> item_0: - tpa tpl_0, item_0 >> args_3: - af callee_0, args_3 >> result_2: + lst >> cargs_0: + = bar_0 >> arg_0: + lst_a cargs_0, arg_0 >> cargs_1: + af callee_0, cargs_1 >> result_2: cc ret_2, result_2 >> result_1: cc ret_1, result_1 >> f2_0: - sr 'f2' >> key_1 - rcs exports_1, key_1, f2_0 >> exports_2: - tpl >> drctvs_0: + str 'f2' >> key_1 + rec_s exports_1, key_1, f2_0 >> exports_2: + lst >> drctvs_0: mod exports_2, drctvs_0 >> mod_0:" `; @@ -44,27 +44,31 @@ exports[`func compiles defaults 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> a_0: - tpt args_0 >> tail_0: + lst_h args_0 >> a_0: + lst_t args_0 >> tail_0: int 12 >> flbk_0: - tph tail_0 >> hdm_0: + lst_h tail_0 >> hdm_0: ifv hdm_0, hdm_0, flbk_0 >> b_0: - tpt tail_0 >> tail_1: - tph tail_1 >> c_0: - tpt tail_1 >> tail_2: - = shrub >> callee_0: - tpl >> tpl_0: - = a_0 >> items_0: - tpc tpl_0, items_0 >> args_1: - af callee_0, args_1 >> result_0: - = bar >> callee_1: - tpl >> args_2: - af callee_1, args_2 >> result_1: - cc ret_0, result_1 + lst_t tail_0 >> tail_1: + lst_h tail_1 >> c_0: + lst_t tail_1 >> tail_2: + fn args_1, ret_1: + lst_h args_1 >> prtl_0: + = shrub >> callee_0: + lst >> cargs_0: + = a_0 >> sprd_0: + lst_c cargs_0, sprd_0 >> cargs_1: + af callee_0, cargs_1 >> pfn_0: + cc ret_1, pfn_0 + >> result_0: + = bar >> callee_1: + lst >> cargs_2: + af callee_1, cargs_2 >> result_1: + cc ret_0, result_1 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -72,32 +76,32 @@ exports[`func compiles destructuring args 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> items_0: - tpt args_0 >> tail_3: - tph items_0 >> a_0: - tpt items_0 >> tail_0: - tph tail_0 >> items_1: - tpt tail_0 >> tail_2: - tph items_1 >> b_0: - tpt items_1 >> tail_1: - tph tail_3 >> items_2: - tpt tail_3 >> tail_5: - tph items_2 >> c_0: - tpt items_2 >> tail_4: - tpr tail_4 >> rtail_0: - tpr rtail_0 >> d_0: - tpl >> tpl_1: + lst_h args_0 >> items_0: + lst_t args_0 >> tail_3: + lst_h items_0 >> a_0: + lst_t items_0 >> tail_0: + lst_h tail_0 >> items_1: + lst_t tail_0 >> tail_2: + lst_h items_1 >> b_0: + lst_t items_1 >> tail_1: + lst_h tail_3 >> items_2: + lst_t tail_3 >> tail_5: + lst_h items_2 >> c_0: + lst_t items_2 >> tail_4: + lst_r tail_4 >> rtail_0: + lst_r rtail_0 >> d_0: + lst >> lst_1: = a_0 >> left_0: = b_0 >> right_0: + left_0, right_0 >> item_1: - tpa tpl_1, item_1 >> tpl_0: + lst_a lst_1, item_1 >> lst_0: = c_0 >> item_0: - tpa tpl_0, item_0 >> result_0: + lst_a lst_0, item_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -105,30 +109,30 @@ exports[`func compiles destructuring recs 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> drec_0: - tpt args_0 >> tail_0: - sr 'a' >> key_0 - rcg drec_0, key_0 >> a_0: - sr 'b' >> key_1 - rcg drec_0, key_1 >> b_0: - tph tail_0 >> items_0: - tpt tail_0 >> tail_2: - tph items_0 >> c_0: - tpt items_0 >> tail_1: - tpr tail_1 >> rtail_0: - tpr rtail_0 >> d_0: - tpl >> tpl_1: + lst_h args_0 >> drec_0: + lst_t args_0 >> tail_0: + str 'a' >> key_0 + rec_g drec_0, key_0 >> a_0: + str 'b' >> key_1 + rec_g drec_0, key_1 >> b_0: + lst_h tail_0 >> items_0: + lst_t tail_0 >> tail_2: + lst_h items_0 >> c_0: + lst_t items_0 >> tail_1: + lst_r tail_1 >> rtail_0: + lst_r rtail_0 >> d_0: + lst >> lst_1: = a_0 >> left_0: = b_0 >> right_0: + left_0, right_0 >> item_1: - tpa tpl_1, item_1 >> tpl_0: + lst_a lst_1, item_1 >> lst_0: = c_0 >> item_0: - tpa tpl_0, item_0 >> result_0: + lst_a lst_0, item_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_2 - rcs exports_0, key_2, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_2 + rec_s exports_0, key_2, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -136,20 +140,20 @@ exports[`func compiles empty arg 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> a_0: - tpt args_0 >> tail_0: - tph tail_0 >> unused_0: - tpt tail_0 >> tail_1: - tph tail_1 >> unused_1: - tpt tail_1 >> tail_2: - tph tail_2 >> b_0: - tpt tail_2 >> tail_3: + lst_h args_0 >> a_0: + lst_t args_0 >> tail_0: + lst_h tail_0 >> unused_0: + lst_t tail_0 >> tail_1: + lst_h tail_1 >> unused_1: + lst_t tail_1 >> tail_2: + lst_h tail_2 >> b_0: + lst_t tail_2 >> tail_3: = b_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -157,16 +161,16 @@ exports[`func compiles empty arg 2`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> unused_0: - tpt args_0 >> tail_0: - tph tail_0 >> b_0: - tpt tail_0 >> tail_1: + lst_h args_0 >> unused_0: + lst_t args_0 >> tail_0: + lst_h tail_0 >> b_0: + lst_t tail_0 >> tail_1: = b_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -174,25 +178,25 @@ exports[`func compiles func of func 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> c_0: - tpt args_0 >> tail_0: + lst_h args_0 >> c_0: + lst_t args_0 >> tail_0: fn args_1, ret_1: - tph args_1 >> d_0: - tpt args_1 >> tail_1: - tph tail_1 >> e_0: - tpt tail_1 >> tail_2: + lst_h args_1 >> d_0: + lst_t args_1 >> tail_1: + lst_h tail_1 >> e_0: + lst_t tail_1 >> tail_2: cn ret_2: - tpl >> tpl_1: + lst >> lst_1: = d_0 >> item_1: - tpa tpl_1, item_1 >> tpl_0: + lst_a lst_1, item_1 >> lst_0: = e_0 >> item_0: - tpa tpl_0, item_0 >> value_0: - tph value_0 >> itm_0: + lst_a lst_0, item_0 >> value_0: + lst_h value_0 >> itm_0: int 2 >> val_1: cn: == itm_0, val_1 >> cond_1: - tpt value_0 >> tail_3: - tph tail_3 >> itm_1: + lst_t value_0 >> tail_3: + lst_h tail_3 >> itm_1: int 1 >> val_0: cn: == itm_1, val_0 >> cond_0: @@ -206,11 +210,11 @@ rec >> exports_0: >> match_1: cif cond_1, match_1 >> match_2: - tph value_0 >> itm_2: + lst_h value_0 >> itm_2: int 1 >> val_3: == itm_2, val_3 >> cond_3: - tpt value_0 >> tail_4: - tph tail_4 >> itm_3: + lst_t value_0 >> tail_4: + lst_h tail_4 >> itm_3: int 2 >> val_2: cn: == itm_3, val_2 >> cond_2: @@ -227,9 +231,9 @@ rec >> exports_0: >> result_0: cc ret_0, result_0 >> fun5_0: - sr 'fun5' >> key_0 - rcs exports_0, key_0, fun5_0 >> exports_1: - tpl >> drctvs_0: + str 'fun5' >> key_0 + rec_s exports_0, key_0, fun5_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -237,10 +241,10 @@ exports[`func compiles other 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> c_0: - tpt args_0 >> tail_0: - tph tail_0 >> d_0: - tpt tail_0 >> tail_1: + lst_h args_0 >> c_0: + lst_t args_0 >> tail_0: + lst_h tail_0 >> d_0: + lst_t tail_0 >> tail_1: int 123 >> x_0: cn ret_1: = ni >> value_0: @@ -270,9 +274,9 @@ rec >> exports_0: ac match_0 >> result_1: cc ret_0, result_1 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -280,24 +284,24 @@ exports[`func compiles spread 1`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> a_0: - tpt args_0 >> tail_0: - tph tail_0 >> b_0: - tpt tail_0 >> tail_1: - tpr tail_1 >> rtail_0: - tpr rtail_0 >> c_0: - tpl >> tpl_1: + lst_h args_0 >> a_0: + lst_t args_0 >> tail_0: + lst_h tail_0 >> b_0: + lst_t tail_0 >> tail_1: + lst_r tail_1 >> rtail_0: + lst_r rtail_0 >> c_0: + lst >> lst_1: = a_0 >> left_0: = b_0 >> right_0: + left_0, right_0 >> item_1: - tpa tpl_1, item_1 >> tpl_0: + lst_a lst_1, item_1 >> lst_0: = c_0 >> item_0: - tpa tpl_0, item_0 >> result_0: + lst_a lst_0, item_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; @@ -305,24 +309,24 @@ exports[`func compiles spread 2`] = ` " rec >> exports_0: fn args_0, ret_0: - tph args_0 >> a_0: - tpt args_0 >> tail_0: - tpr tail_0 >> rtail_0: - tph rtail_0 >> c_0: - tpt rtail_0 >> tail_1: - tpr tail_1 >> b_0: - tpl >> tpl_2: + lst_h args_0 >> a_0: + lst_t args_0 >> tail_0: + lst_r tail_0 >> rtail_0: + lst_h rtail_0 >> c_0: + lst_t rtail_0 >> tail_1: + lst_r tail_1 >> b_0: + lst >> lst_2: = a_0 >> item_2: - tpa tpl_2, item_2 >> tpl_1: + lst_a lst_2, item_2 >> lst_1: = b_0 >> item_1: - tpa tpl_1, item_1 >> tpl_0: + lst_a lst_1, item_1 >> lst_0: = c_0 >> item_0: - tpa tpl_0, item_0 >> result_0: + lst_a lst_0, item_0 >> result_0: cc ret_0, result_0 >> fun_0: - sr 'fun' >> key_0 - rcs exports_0, key_0, fun_0 >> exports_1: - tpl >> drctvs_0: + str 'fun' >> key_0 + rec_s exports_0, key_0, fun_0 >> exports_1: + lst >> drctvs_0: mod exports_1, drctvs_0 >> mod_0:" `; diff --git a/src/ir/literals/record.fnk b/src/ir/literals/record.fnk index 8315566..8c0e0d1 100644 --- a/src/ir/literals/record.fnk +++ b/src/ir/literals/record.fnk @@ -4,6 +4,18 @@ +members_as_rec = fn expr, val: + match expr: + {type: 'member'}: + kv = {type: 'rec:kv', left: expr.right, right: val} + nval = {type: 'rec', exprs: [kv]} + members_as_rec expr.left, nval + else: + kv = {type: 'rec:kv', left: expr, right: val} + {type: 'rec', exprs: [kv]} + + + transform_key = fn expr, ctx: match expr: {type: 'ident'}: @@ -33,6 +45,7 @@ transform_kv = fn expr, out_id, ctx: {type: 'spread'}: [val, val_id, next_ctx] = transform expr.right, 'sprd', key_ctx [[...val, ['rec_m', [rec_id, val_id], [out_id], {loc: expr.loc}]], rec_id , next_ctx] + else: [key, key_id, val_ctx] = transform_key expr.left, key_ctx [val, val_id, next_ctx] = transform_val expr, key_id, val_ctx @@ -44,6 +57,11 @@ transform_entries = fn [expr=false, ...rest], ctx, result_id, out=[]: match expr: false: [out, result_id, ctx] + + {left.type: 'member'}: + {exprs} = members_as_rec expr.left, expr.right + transform_entries [...exprs, ...rest], ctx, result_id, out + else: [kv, rec_id, next_ctx] = transform_kv expr, result_id, ctx transform_entries rest, next_ctx, rec_id, [...kv, ...out] diff --git a/src/ir/literals/record.test.fnk b/src/ir/literals/record.test.fnk index 226dbaf..7bcf20a 100644 --- a/src/ir/literals/record.test.fnk +++ b/src/ir/literals/record.test.fnk @@ -1,4 +1,4 @@ -{skip, describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' +{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' {fink2lir, fink2lir_o} = import '../../testing/generate.fnk' @@ -51,7 +51,7 @@ describe 'record', fn: to_match_snapshot - skip.it 'compiles member expr as keys', fn: + it 'compiles member expr as keys', fn: expect fink2lir "foo = {...bar, spam.ham.ni: 'ni', na: 1234, ...nu}" to_match_snapshot @@ -104,7 +104,7 @@ describe 'unpacking record', fn: to_match_snapshot - skip.it 'compiles member expr as keys', fn: + it 'compiles member expr as keys', fn: expect fink2lir "{spam.ham.ni: ni, ...rest} = foo" to_match_snapshot diff --git a/src/ir/literals/record.test.fnk.snap b/src/ir/literals/record.test.fnk.snap index 3d579e8..a6fad39 100644 --- a/src/ir/literals/record.test.fnk.snap +++ b/src/ir/literals/record.test.fnk.snap @@ -88,56 +88,57 @@ rec >> exports_0: `; exports[`record compiles member expr as keys 1`] = ` -"let _do_result; - -{ - let ˆrec_1 = { ...bar - }; - ˆrec_1 = { ...ˆrec_1, - spam: { ...ˆrec_1?.spam, - ham: { ...ˆrec_1?.spam?.ham, - ni: \`ni\` - } - } - }; - ˆrec_1 = { ...ˆrec_1, - na: 1234 - }; - ˆrec_1 = { ...ˆrec_1, - ...nu - }; - _do_result = ˆrec_1; -} -export const foo = _do_result; -_do_result = undefined;" +" +rec >> exports_0: + rec >> rec_5: + = bar >> sprd_1: + rec_m rec_5, sprd_1 >> rec_2: + str 'spam' >> key_1 + rec >> rec_3: + str 'ham' >> key_2 + rec >> rec_4: + str 'ni' >> key_3 + str 'ni' >> str_0 + strt str_0 >> val_3: + rec_s rec_4, key_3, val_3 >> val_2: + rec_s rec_3, key_2, val_2 >> val_1: + rec_s rec_2, key_1, val_1 >> rec_1: + str 'na' >> key_0 + int 1234 >> val_0: + rec_s rec_1, key_0, val_0 >> rec_0: + = nu >> sprd_0: + rec_m rec_0, sprd_0 >> foo_0: + str 'foo' >> key_4 + rec_s exports_0, key_4, foo_0 >> exports_1: + lst >> drctvs_0: + mod exports_1, drctvs_0 >> mod_0:" `; exports[`record compiles member expr as keys 2`] = ` -"let _do_result; - -{ - let ˆrec_1 = { ...bar - }; - ˆrec_1 = { ...ˆrec_1, - spam: { ...ˆrec_1?.spam, - ham: (() => { - let ˆrec_2 = {}; - ˆrec_2 = { ...ˆrec_2, - ni: { ...ˆrec_2?.ni, - na: \`ni\` - } - }; - return ˆrec_2; - })() - } - }; - ˆrec_1 = { ...ˆrec_1, - ...nu - }; - _do_result = ˆrec_1; -} -export const foo = _do_result; -_do_result = undefined;" +" +rec >> exports_0: + rec >> rec_5: + = bar >> sprd_1: + rec_m rec_5, sprd_1 >> rec_1: + str 'spam' >> key_0 + rec >> rec_2: + str 'ham' >> key_1 + rec >> rec_3: + str 'ni' >> key_2 + rec >> rec_4: + str 'na' >> key_3 + str 'ni' >> str_0 + strt str_0 >> val_3: + rec_s rec_4, key_3, val_3 >> val_2: + rec_s rec_3, key_2, val_2 >> val_1: + rec_s rec_2, key_1, val_1 >> val_0: + rec_s rec_1, key_0, val_0 >> rec_0: + = nu >> sprd_0: + rec_m rec_0, sprd_0 >> foo_0: + str 'foo' >> key_4 + rec_s exports_0, key_4, foo_0 >> exports_1: + lst >> drctvs_0: + mod exports_1, drctvs_0 >> mod_0:" `; exports[`record compiles shorthand 1`] = ` @@ -260,46 +261,60 @@ rec >> exports_0: `; exports[`unpacking record compiles member expr as keys 1`] = ` -"const { - spam: { - ham: { - ni: ni - } - }, - ...rest -} = foo;" +" +rec >> exports_0: + = foo >> right_0: + str 'spam' >> key_0 + rec_g right_0, key_0 >> val_0: + str 'ham' >> key_1 + rec_g val_0, key_1 >> val_1: + str 'ni' >> key_2 + rec_g val_1, key_2 >> ni_0: + rec_d right_0, key_0 >> rest_0: + lst >> drctvs_0: + mod exports_0, drctvs_0 >> mod_0:" `; exports[`unpacking record compiles member expr as keys 2`] = ` -"const { - spam: { - ham: { - ni: { - ni: nu, - foo: { - bar: bar - } - } - } - }, - ...rest -} = foo;" +" +rec >> exports_0: + = foo >> right_0: + str 'spam' >> key_0 + rec_g right_0, key_0 >> val_0: + str 'ham' >> key_1 + rec_g val_0, key_1 >> val_1: + str 'ni' >> key_2 + rec_g val_1, key_2 >> val_2: + str 'ni' >> key_3 + rec_g val_2, key_3 >> nu_0: + str 'foo' >> key_4 + rec_g val_2, key_4 >> val_3: + str 'bar' >> key_5 + rec_g val_3, key_5 >> bar_0: + rec_d right_0, key_0 >> rest_0: + lst >> drctvs_0: + mod exports_0, drctvs_0 >> mod_0:" `; exports[`unpacking record compiles member expr as keys 3`] = ` -"const { - \\"foo-bar\\": { - \\"spam-ham\\": { - ni: { - ni: nu, - foo: { - bar: bar - } - } - } - }, - ...rest -} = foo;" +" +rec >> exports_0: + = foo >> right_0: + str 'foo-bar' >> key_0 + rec_g right_0, key_0 >> val_0: + str 'spam-ham' >> key_1 + rec_g val_0, key_1 >> val_1: + str 'ni' >> key_2 + rec_g val_1, key_2 >> val_2: + str 'ni' >> key_3 + rec_g val_2, key_3 >> nu_0: + str 'foo' >> key_4 + rec_g val_2, key_4 >> val_3: + str 'bar' >> key_5 + rec_g val_3, key_5 >> bar_0: + rec_d right_0, key_0 >> rest_0: + lst >> drctvs_0: + mod exports_0, drctvs_0 >> mod_0:" `; exports[`unpacking record compiles nested 1`] = ` diff --git a/src/ir/module/init.test.fnk b/src/ir/module/init.test.fnk index 36bd533..27d80e0 100644 --- a/src/ir/module/init.test.fnk +++ b/src/ir/module/init.test.fnk @@ -26,4 +26,5 @@ describe 'module', fn: foo_bar = 1234 foo-bar = 1234 " - to_match_snapshot \ No newline at end of file + to_match_snapshot + diff --git a/src/js/async/init.test.fnk b/src/js/async/init.test.fnk index 8f164e0..04dffec 100644 --- a/src/js/async/init.test.fnk +++ b/src/js/async/init.test.fnk @@ -1,4 +1,4 @@ -{skip, describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' +{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' {fink2js} = import '../../testing/generate.fnk' @@ -13,7 +13,7 @@ describe 'await', fn: task3 = fn foo: spam = await foo _ - bar + 123 + bar + 123 + spam a_gen = unfold fn curr=0: match shrub: @@ -23,14 +23,3 @@ describe 'await', fn: await ni ' to_match_snapshot - - - skip.it 'handles awaiting async iterables', fn: - expect - fink2js ' - [await foo, bar] = pipe: - unfold fn cntr=0: - await cntr + 1 - ' - to_match_snapshot - diff --git a/src/js/async/init.test.fnk.snap b/src/js/async/init.test.fnk.snap index 2d8b6a9..e22fbf5 100644 --- a/src/js/async/init.test.fnk.snap +++ b/src/js/async/init.test.fnk.snap @@ -9,8 +9,8 @@ const task2_0 = async foo_1 => { return await (foo_1 + 4); }; -const task3_0 = foo_2 => { - return bar + 123; +const task3_0 = async foo_2 => { + return bar + 123 + (await foo_2()); }; const a_gen_0 = unfold(async hdm_0 => { @@ -28,24 +28,3 @@ export const task1 = task1_0, task3 = task3_0, a_gen = a_gen_0;" `; - -exports[`await handles awaiting async iterables 1`] = ` -"let _do_result; - -{ - let _do_result2; - - { - let ˆpipe_result_3 = undefined; - _do_result2 = ˆpipe_result_3 = unfold(async (cntr = 0) => (await cntr) + 1)(ˆpipe_result_3); - } - const ˆitems_1 = _do_result2; - _do_result2 = undefined; - const ˆiter_2 = ( - /*istanbul ignore next*/ - ˆitems_1[Symbol.asyncIterator] || ˆitems_1[Symbol.iterator]).call(ˆitems_1); - _do_result = [(await ˆiter_2.next()).value, (await ˆiter_2.next()).value]; -} -const [foo, bar] = _do_result; -_do_result = undefined;" -`; diff --git a/src/js/conditionals/match.test.fnk b/src/js/conditionals/match.test.fnk index 3fefd73..6a62bb2 100644 --- a/src/js/conditionals/match.test.fnk +++ b/src/js/conditionals/match.test.fnk @@ -206,6 +206,7 @@ describe 'match records', fn: {foo: 4, ni: {na, nu}}: spam + ni {foo: 1, foo: {bar: 'spam'}, shrub: {na: 'nu'}}: ni {ni: {len: 1}, na: {len: 1}}: na + {ni: [foo, 1234]}: na " to_match_snapshot @@ -229,20 +230,16 @@ describe 'match records', fn: to_match_snapshot - skip.it 'matches member expr keys', fn: + it 'matches member expr keys', fn: expect fink2js ' - match foo: + match shrub: {foo.bar.spam: ham}: spam + {foo.bar.spam: {ham.ni: nu}}: ham + {foo: {bar.spam: {ham.ni: nu}, spam}}: ham ' to_match_snapshot - expect - fink2js ' - match foo: - {foo.bar.spam: {ham.ni: nu}}: spam - ' - to_match_snapshot it 'matches value assertions', fn: diff --git a/src/js/conditionals/match.test.fnk.snap b/src/js/conditionals/match.test.fnk.snap index 5ccbd1a..86c5154 100644 --- a/src/js/conditionals/match.test.fnk.snap +++ b/src/js/conditionals/match.test.fnk.snap @@ -401,12 +401,12 @@ exports[`match records matches calculated props 1`] = ` "let ret_0; ret_0: { - const itm_0 = shrub[a]; + const itm_0 = shrub?.[a]; /* istanbul ignore else */ - if (itm_0.b === b) { + if (itm_0?.b === b) { /* istanbul ignore else */ - if (itm_0.c === c) { + if (itm_0?.c === c) { ret_0 = ni; break ret_0; } @@ -418,100 +418,60 @@ export const ;" `; exports[`match records matches member expr keys 1`] = ` -"{ - ˆmatch_2: { - const ˆvalue_1 = foo; - - if (ˆvalue_1 != null) { - const { - foo: ˆp_3 - } = ˆvalue_1; - - if (ˆp_3 != null) { - const { - bar: ˆp_4 - } = ˆp_3; - - if (ˆp_4 != null) { - const { - spam: ˆp_5 - } = ˆp_4; - - if (ˆp_5 === ham) { - spam; - break ˆmatch_2; - } - } - } - } +"let ret_0; + +ret_0: { + const itm_0 = shrub?.foo; + + /* istanbul ignore else */ + if (shrub?.foo?.bar?.spam === ham) { + ret_0 = spam; + break ret_0; } -}" -`; -exports[`match records matches member expr keys 2`] = ` -"{ - ˆmatch_2: { - const ˆvalue_1 = foo; - - if (ˆvalue_1 != null) { - const { - foo: ˆp_3 - } = ˆvalue_1; - - if (ˆp_3 != null) { - const { - bar: ˆp_4 - } = ˆp_3; - - if (ˆp_4 != null) { - const { - spam: ˆp_5 - } = ˆp_4; - - if (ˆp_5 != null) { - const { - ham: ˆp_6 - } = ˆp_5; - - if (ˆp_6 != null) { - const { - ni: ˆp_7 - } = ˆp_6; - - if (ˆp_7 === nu) { - spam; - break ˆmatch_2; - } - } - } - } - } + /* istanbul ignore else */ + if (shrub?.foo?.bar?.spam?.ham?.ni === nu) { + ret_0 = ham; + break ret_0; + } + + /* istanbul ignore else */ + if (itm_0?.bar?.spam?.ham?.ni === nu) { + /* istanbul ignore else */ + if (itm_0?.spam === spam) { + ret_0 = ham; + break ret_0; } } -}" +} + +const mex_0 = ret_0; +export const ;" `; exports[`match records matches props 1`] = ` "let ret_0; ret_0: { + const itm_0 = shrub?.ni; + /* istanbul ignore else */ - if (shrub.foo === foo) { + if (shrub?.foo === foo) { /* istanbul ignore else */ - if (shrub.bar === bar) { + if (shrub?.bar === bar) { ret_0 = ni; break ret_0; } } - const itm_10 = shrub.ni; + const itm_13 = shrub?.ni; /* istanbul ignore else */ - if (shrub.foo === 4) { + if (shrub?.foo === 4) { /* istanbul ignore else */ - if (itm_10.na === na) { + if (itm_13?.na === na) { /* istanbul ignore else */ - if (itm_10.nu === nu) { + if (itm_13?.nu === nu) { ret_0 = spam + ni; break ret_0; } @@ -519,11 +479,11 @@ ret_0: { } /* istanbul ignore else */ - if (shrub.foo === 1) { + if (shrub?.foo === 1) { /* istanbul ignore else */ - if (shrub.foo.bar === \`spam\`) { + if (shrub?.foo?.bar === \`spam\`) { /* istanbul ignore else */ - if (shrub.shrub.na === \`nu\`) { + if (shrub?.shrub?.na === \`nu\`) { ret_0 = ni; break ret_0; } @@ -531,9 +491,18 @@ ret_0: { } /* istanbul ignore else */ - if (shrub.ni.len === 1) { + if (shrub?.ni?.len === 1) { + /* istanbul ignore else */ + if (shrub?.na?.len === 1) { + ret_0 = na; + break ret_0; + } + } + + /* istanbul ignore else */ + if (itm_0[0] === foo) { /* istanbul ignore else */ - if (shrub.na.len === 1) { + if (itm_0[1] === 1234) { ret_0 = na; break ret_0; } @@ -554,9 +523,9 @@ ret_0: { } = shrub; /* istanbul ignore else */ - if (spread_0.bar === bar) { + if (spread_0?.bar === bar) { /* istanbul ignore else */ - if (spread_0.spam === spam) { + if (spread_0?.spam === spam) { ret_0 = ni; break ret_0; } @@ -575,31 +544,31 @@ ret_0: { const key_2 = \`spam\`; /* istanbul ignore else */ - if (true === !foo.spam) { + if (true === !foo?.spam) { ret_0 = ni; break ret_0; } /* istanbul ignore else */ - if (true === foo.spam > 123) { + if (true === foo?.spam > 123) { ret_0 = ni; break ret_0; } /* istanbul ignore else */ - if (true === foo.spam()) { + if (true === (foo?.spam)()) { ret_0 = ni; break ret_0; } /* istanbul ignore else */ - if (true === foo.spam.is_foo()) { + if (true === (foo?.spam).is_foo()) { ret_0 = ni; break ret_0; } /* istanbul ignore else */ - if (true === is_foo(foo.spam)) { + if (true === is_foo(foo?.spam)) { ret_0 = ni; break ret_0; } @@ -610,7 +579,7 @@ ret_0: { } = foo; /* istanbul ignore else */ - if (foo.spam === spam) { + if (foo?.spam === spam) { /* istanbul ignore else */ if (true === is_empty(spread_1)) { ret_0 = ni; @@ -624,7 +593,7 @@ ret_0: { } = foo; /* istanbul ignore else */ - if (foo.spam === spam) { + if (foo?.spam === spam) { /* istanbul ignore else */ if (true === _in_(\`foo\`, spread_0)) { ret_0 = ni; @@ -633,7 +602,7 @@ ret_0: { } /* istanbul ignore else */ - if (undefined !== foo.spam) { + if (undefined !== foo?.spam) { ret_0 = true; break ret_0; } diff --git a/src/js/init.fnk b/src/js/init.fnk index b92eb35..111d60c 100644 --- a/src/js/init.fnk +++ b/src/js/init.fnk @@ -30,8 +30,6 @@ {inc_ref} = import '../ir/context.fnk' -{timed} = import '../perf.fnk' - add_transformers = fn ctx: pipe ctx: diff --git a/src/js/literals/record.fnk b/src/js/literals/record.fnk index 3c99ca6..3ef96d6 100644 --- a/src/js/literals/record.fnk +++ b/src/js/literals/record.fnk @@ -1,7 +1,7 @@ types = import '@babel/types' { objectExpression, objectProperty, objectPattern - memberExpression, identifier + memberExpression, identifier, optionalMemberExpression spreadElement, restElement, variableDeclaration variableDeclarator, stringLiteral } = types @@ -62,20 +62,24 @@ trandform_rec_set = fn expr, ctx: transform_rec_get = fn expr, ctx: - [ , [rec_id, key_id] , [result_id]] = expr + [op , [rec_id, key_id] , [result_id]] = expr rec_js = get_js rec_id, ctx key = get_js_literal key_id, ctx - js = match key: + [computed, final_key] = match key: {type: 'TemplateLiteral', quasis: [?, ?]}: - memberExpression rec_js, key, true + [true, key] {type: 'TemplateLiteral', quasis: [{value: {raw: is_js_ident ?}}]}: {quasis: [{value: {raw: value}}]} = key - memberExpression rec_js, identifier value + [false, identifier value] else: - memberExpression rec_js, key, true + [true, key] + + js = match op: + 'rec_go': optionalMemberExpression rec_js, final_key, computed, true + else: memberExpression rec_js, final_key, computed set_js result_id, js, ctx @@ -135,6 +139,7 @@ add_record = fn ctx: pipe ctx: add 'rec', transform_rec add 'rec_g', transform_rec_get + add 'rec_go', transform_rec_get add 'rec_s', trandform_rec_set add 'rec_d', transform_rec_del_keys add 'rec_m', transform_rec_merge diff --git a/src/js/literals/record.test.fnk b/src/js/literals/record.test.fnk index d0174d8..119a831 100644 --- a/src/js/literals/record.test.fnk +++ b/src/js/literals/record.test.fnk @@ -1,4 +1,4 @@ -{skip, describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' +{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' {fink2js} = import '../../testing/generate.fnk' @@ -70,7 +70,7 @@ describe 'record', fn: to_match_snapshot - skip.it 'compiles member expr as keys', fn: + it 'compiles member expr as keys', fn: expect fink2js "foo = {...bar, spam.ham.ni: 'ni', na: 1234, ...nu}" to_match_snapshot @@ -145,7 +145,7 @@ describe 'unpacking record', fn: to_match_snapshot - skip.it 'compiles member expr as keys', fn: + it 'compiles member expr as keys', fn: expect fink2js ' {spam.ham.ni: ni, ...rest} = foo diff --git a/src/js/literals/record.test.fnk.snap b/src/js/literals/record.test.fnk.snap index a3bb35c..f6d2e27 100644 --- a/src/js/literals/record.test.fnk.snap +++ b/src/js/literals/record.test.fnk.snap @@ -39,56 +39,30 @@ export const obj7 = obj7_0;" `; exports[`record compiles member expr as keys 1`] = ` -"let _do_result; - -{ - let ˆrec_1 = { ...bar - }; - ˆrec_1 = { ...ˆrec_1, - spam: { ...ˆrec_1?.spam, - ham: { ...ˆrec_1?.spam?.ham, - ni: \`ni\` - } +"const foo_0 = { ...bar, + spam: { + ham: { + ni: \`ni\` } - }; - ˆrec_1 = { ...ˆrec_1, - na: 1234 - }; - ˆrec_1 = { ...ˆrec_1, - ...nu - }; - _do_result = ˆrec_1; -} -export const foo = _do_result; -_do_result = undefined;" + }, + na: 1234, + ...nu +}; +export const foo = foo_0;" `; exports[`record compiles member expr as keys 2`] = ` -"let _do_result; - -{ - let ˆrec_1 = { ...bar - }; - ˆrec_1 = { ...ˆrec_1, - spam: { ...ˆrec_1?.spam, - ham: (() => { - let ˆrec_2 = {}; - ˆrec_2 = { ...ˆrec_2, - ni: { ...ˆrec_2?.ni, - na: \`ni\` - } - }; - return ˆrec_2; - })() +"const foo_0 = { ...bar, + spam: { + ham: { + ni: { + na: \`ni\` + } } - }; - ˆrec_1 = { ...ˆrec_1, - ...nu - }; - _do_result = ˆrec_1; -} -export const foo = _do_result; -_do_result = undefined;" + }, + ...nu +}; +export const foo = foo_0;" `; exports[`record compiles shorthand 1`] = ` @@ -170,46 +144,35 @@ export const out = out_0;" `; exports[`unpacking record compiles member expr as keys 1`] = ` -"const { - spam: { - ham: { - ni: ni - } - }, - ...rest -} = foo;" +"const key_0 = \`spam\`; +const { + spam: _key_0, + ...rest_0 +} = foo; +const out_0 = [foo.spam.ham.ni, rest_0]; +export const out = out_0;" `; exports[`unpacking record compiles member expr as keys 2`] = ` -"const { - spam: { - ham: { - ni: { - ni: nu, - foo: { - bar: bar - } - } - } - }, - ...rest -} = foo;" +"const key_0 = \`spam\`; +const val_2 = foo.spam.ham.ni; +const { + spam: _key_0, + ...rest_0 +} = foo; +const out_0 = [val_2.ni, val_2.foo.bar, rest_0]; +export const out = out_0;" `; exports[`unpacking record compiles member expr as keys 3`] = ` -"const { - \\"foo-bar\\": { - \\"spam-ham\\": { - ni: { - ni: nu, - foo: { - bar: bar - } - } - } - }, - ...rest -} = foo;" +"const key_0 = \`foo-bar\`; +const val_2 = foo[\`foo-bar\`][\`spam-ham\`].ni; +const { + \\"foo-bar\\": _key_0, + ...rest_0 +} = foo; +const out_0 = [val_2.ni, val_2.foo.bar, rest_0]; +export const out = out_0;" `; exports[`unpacking record compiles non js idents 1`] = ` diff --git a/src/js/module/init.fnk b/src/js/module/init.fnk index ac78b1c..10ecbcd 100644 --- a/src/js/module/init.fnk +++ b/src/js/module/init.fnk @@ -1,6 +1,6 @@ types = import '@babel/types' { - file, program, exportNamedDeclaration, exportSpecifier, identifier + file, program, exportNamedDeclaration, identifier assignmentExpression, expressionStatement memberExpression, callExpression, objectProperty, objectPattern variableDeclaration, variableDeclarator @@ -50,25 +50,24 @@ transform_specifiers = fn {specifiers, source}: expressionStatement init -# ImportNamespaceSpecifier: + module_transforms = rec: ImportDeclaration: fn path: path.replaceWith transform_specifiers path.node no_result ExportNamedDeclaration: fn path: - {specifiers} = path.node + {declaration: {declarations}} = path.node + exports = identifier 'exports' - pipe specifiers: - fold fn {local, exported}: + pipe declarations: + fold fn {id, init}: path.insertAfter expressionStatement assignmentExpression '=' - memberExpression - identifier 'exports' - exported - local + memberExpression exports, id + init path.remove _ no_result @@ -80,7 +79,7 @@ transform_mod_exports = fn expr, ctx: decls = pipe get_js exports_id, ctx: ?.properties - map fn {key, value, loc}: + map fn {key, value}: name = match key: {type: 'StringLiteral'}: key.value else: key.name @@ -127,3 +126,4 @@ add_module = fn ctx: pipe ctx: add 'mod', transform_mod_exports + diff --git a/src/js/module/init.test.fnk b/src/js/module/init.test.fnk index 7df2bc1..2b066d3 100644 --- a/src/js/module/init.test.fnk +++ b/src/js/module/init.test.fnk @@ -3,17 +3,12 @@ describe 'module', fn: - it 'handles comments', fn: + it 'handles directives', fn: expect fink2js " #!/usr/bin/env node - # leading comment - - # expr comment foo = 1234 - - # trailing comment " to_match_snapshot @@ -26,4 +21,14 @@ describe 'module', fn: foo_bar = 1234 foo-bar = 1234 " + to_match_snapshot + + + it 'handles side effects', fn: + expect + fink2js " + foo bar + shrub.ni foo + spam = ni + " to_match_snapshot \ No newline at end of file diff --git a/src/js/module/init.test.fnk.snap b/src/js/module/init.test.fnk.snap index 4296d59..1cfd034 100644 --- a/src/js/module/init.test.fnk.snap +++ b/src/js/module/init.test.fnk.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`module handles comments 1`] = ` +exports[`module handles directives 1`] = ` "#!/usr/bin/env node const foo_0 = 1234; export const foo = foo_0;" @@ -22,3 +22,9 @@ export const ˆdelete = delete_0, foo_bar = foo_bar_0, fooᜭbar = fooᜭbar_0;" `; + +exports[`module handles side effects 1`] = ` +"foo(bar); +shrub.ni(foo); +export const spam = ni;" +`; diff --git a/src/js/transform.fnk b/src/js/transform.fnk index e83aec3..bccc973 100644 --- a/src/js/transform.fnk +++ b/src/js/transform.fnk @@ -1,6 +1,6 @@ types = import '@babel/types' { - binaryExpression, unaryExpression + binaryExpression, unaryExpression, expressionStatement identifier, variableDeclaration, variableDeclarator } = types @@ -71,11 +71,11 @@ transform_exprs = fn [expr=false, ...exprs], ctx, body=[]: transform_exprs exprs, next_ctx, [...body, js] [ , , [?]]: - [, , [res_id]] = expr + [op, , [res_id]] = expr next_ctx = transform expr, ctx - match get_refs res_id, next_ctx: - ? > 1: + match [op, get_refs res_id, next_ctx]: + [, ? > 1]: val = get_js_literal res_id, next_ctx js = match val: {type: 'VariableDeclaration'}: @@ -85,6 +85,13 @@ transform_exprs = fn [expr=false, ...exprs], ctx, body=[]: variableDeclaration 'const', [variableDeclarator id, val] transform_exprs exprs, next_ctx, [...body, js] + + # unused calls assumed to have side effects + ['af', ? == 0]: + val = get_js_literal res_id, next_ctx + js = expressionStatement val + transform_exprs exprs, next_ctx, [...body, js] + else: transform_exprs exprs, next_ctx, body