diff --git a/src/js/types.fnk b/src/js/types.fnk index 75ecf9c..c99aa6f 100644 --- a/src/js/types.fnk +++ b/src/js/types.fnk @@ -31,6 +31,10 @@ not_nullish = fn value: binaryExpression '!=', value, nullLiteral _ +not_undefiend = fn value: + binaryExpression '!==', value, undef _ + + ident = fn name, ctx: identifier escape_ident name, ctx diff --git a/src/lang/async/init.test.fnk b/src/lang/async/init.test.fnk index 5de65a0..f6c6462 100644 --- a/src/lang/async/init.test.fnk +++ b/src/lang/async/init.test.fnk @@ -12,7 +12,6 @@ describe 'await', fn: task2 = fn foo: await (foo + 4) task3 = fn foo: - bar = await foo () spam = await foo _ bar + 123 diff --git a/src/lang/async/init.test.fnk.snap b/src/lang/async/init.test.fnk.snap index 653a530..d9b2def 100644 --- a/src/lang/async/init.test.fnk.snap +++ b/src/lang/async/init.test.fnk.snap @@ -4,7 +4,6 @@ exports[`await compiles 1`] = ` "export const task1 = async foo => -(await foo); export const task2 = async foo => await (foo + 4); export const task3 = async foo => { - const bar = await foo(); const spam = await foo(); return bar + 123; }; diff --git a/src/lang/call/call.fnk b/src/lang/call/call.fnk index ff696af..34410d1 100644 --- a/src/lang/call/call.fnk +++ b/src/lang/call/call.fnk @@ -1,7 +1,7 @@ babel_types = import '@babel/types' {callExpression, identifier} = babel_types -{map, filter, zip, is_empty, length} = import '@fink/std-lib/iter.fnk' +{map, filter, zip, length} = import '@fink/std-lib/iter.fnk' {transform, map_with_ctx, collect_with_ctx} = import '../transform.fnk' {transform_with_partial, partial_wrapper, no_wrapper} = import '../partial/init.fnk' @@ -24,9 +24,6 @@ transform_single_arg = fn [expr], ctx: match expr: {type: 'empty'}: [[], ctx] - # TODO: remove in favour of using _ as empty? - {type: 'group', exprs: is_empty ?}: - [[], ctx] else: transform_multiple_args [expr], ctx diff --git a/src/lang/call/call.test.fnk b/src/lang/call/call.test.fnk index 744581e..6af2a45 100644 --- a/src/lang/call/call.test.fnk +++ b/src/lang/call/call.test.fnk @@ -8,10 +8,9 @@ describe 'call', fn: fink2js ' call1 = a ni, x=123, ...x call2 = a ni - call3 = a () - call4 = a _ - call5 = a fn x: x * 2 - call6 = a foo, , bar + call3 = a _ + call4 = a fn x: x * 2 + call5 = a foo, , bar ' to_match_snapshot diff --git a/src/lang/call/call.test.fnk.snap b/src/lang/call/call.test.fnk.snap index e162330..f456939 100644 --- a/src/lang/call/call.test.fnk.snap +++ b/src/lang/call/call.test.fnk.snap @@ -4,9 +4,8 @@ exports[`call compiles 1`] = ` "export const call1 = a(ni, x = 123, ...x); export const call2 = a(ni); export const call3 = a(); -export const call4 = a(); -export const call5 = a(x => x * 2); -export const call6 = a(foo, undefined, bar);" +export const call4 = a(x => x * 2); +export const call5 = a(foo, undefined, bar);" `; exports[`call compiles as partial 1`] = ` diff --git a/src/lang/conditionals/match.fnk b/src/lang/conditionals/match.fnk index fcd1c65..b5189ee 100644 --- a/src/lang/conditionals/match.fnk +++ b/src/lang/conditionals/match.fnk @@ -7,7 +7,7 @@ babel_types = import '@babel/types' } = babel_types {map, filter, length, is_empty} = import '@fink/std-lib/iter.fnk' -{eq, not_nullish, typof, consts, unique_ident} = import '../../js/types.fnk' +{eq, not_nullish, not_undefiend, typof, consts, unique_ident} = import '../../js/types.fnk' {get_key} = import '../literals/record.fnk' {wrap_with_comment_loc} = import '../comments/init.fnk' @@ -31,14 +31,19 @@ is_iterable = fn value: comp = fn id, expected, ctx: - value_ctx = {...ctx, partial_ident: id} - [wrap_with_partial, value, {partial_ident: _, ...next_ctx}] = transform_with_partial expected, value_ctx, false + match expected: + {type: 'partial'}: + cond = not_undefiend id + [cond, ctx] + else: + value_ctx = {...ctx, partial_ident: id} + [wrap_with_partial, value, {partial_ident: _, ...next_ctx}] = transform_with_partial expected, value_ctx, false - cond = match wrap_with_partial: - false: eq id, value - else: value + cond = match wrap_with_partial: + false: eq id, value + else: value - [cond, next_ctx] + [cond, next_ctx] diff --git a/src/lang/conditionals/match.test.fnk b/src/lang/conditionals/match.test.fnk index 3af5434..d28ee3e 100644 --- a/src/lang/conditionals/match.test.fnk +++ b/src/lang/conditionals/match.test.fnk @@ -30,11 +30,13 @@ describe 'match', fn: ? > 123: ni # simple call - ? (): ni ? _: ni # simple as call arg shrub ?: ni + + # any value + ?: true ' to_match_snapshot @@ -69,6 +71,7 @@ describe 'match iterables', fn: match shrub: # deep iterable comparison [1, 2, [ni]]: ni + # TODO: fix semantics for matching [], {} [1, 2, [], {}]: foo [1, [2, 3], 4]: bar [1, [2, [3, 4]], [5, 6], 7]: spam @@ -96,15 +99,16 @@ describe 'match iterables', fn: # nested unary [not ?]: ni + # any value + [?]: true + # nested binary [? > 123]: ni # nested call - [? ()]: ni [? _]: ni # nested member call - [?.is_foo ()]: ni [?.is_foo _]: ni # nested as call arg @@ -122,7 +126,9 @@ describe 'match records', fn: expect fink2js " match shrub: + # TODO: fix semantics for matching {} {foo: {}}: spam + ni + # TODO: fix semantics for matching [] {foo: []}: spam + ni {foo: 4, ni: {na, nu}}: spam + ni {foo: 1, foo: {bar: 'spam'}, shrub: {na: 'nu'}}: ni @@ -178,11 +184,9 @@ describe 'match records', fn: {spam: ? > 123}: ni # nested call - {spam: ? ()}: ni {spam: ? _}: ni # nested member call - {spam: ?.is_foo ()}: ni {spam: ?.is_foo _}: ni # nested as call arg @@ -190,6 +194,9 @@ describe 'match records', fn: {spam, ...is_empty ?}: ni {spam, ...("foo" in ?)}: ni + + # any value + {spam: ?}: true ' to_match_snapshot diff --git a/src/lang/conditionals/match.test.fnk.snap b/src/lang/conditionals/match.test.fnk.snap index 175ffd2..1f62062 100644 --- a/src/lang/conditionals/match.test.fnk.snap +++ b/src/lang/conditionals/match.test.fnk.snap @@ -117,31 +117,33 @@ exports[`match iterables matches value assertions 1`] = ` } } - // nested binary + // any value if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { const [ˆa_4] = ˆvalue_1; - // nested binary - if (ˆa_4 > 123) { - ni; + // any value + if (ˆa_4 !== undefined) { + true; break ˆmatch_2; } } - // nested call + // nested binary if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { const [ˆa_5] = ˆvalue_1; - // nested call - if (ˆa_5()) { + // nested binary + if (ˆa_5 > 123) { ni; break ˆmatch_2; } } + // nested call if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { const [ˆa_6] = ˆvalue_1; + // nested call if (ˆa_6()) { ni; break ˆmatch_2; @@ -159,37 +161,28 @@ exports[`match iterables matches value assertions 1`] = ` } } - if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { - const [ˆa_8] = ˆvalue_1; - - if (ˆa_8.is_foo()) { - ni; - break ˆmatch_2; - } - } - // nested as call arg if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { - const [ˆa_9] = ˆvalue_1; + const [ˆa_8] = ˆvalue_1; // nested as call arg - if (is_foo(ˆa_9)) { + if (is_foo(ˆa_8)) { ni; break ˆmatch_2; } } if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { - const [ˆa_10, ...ˆa_11] = ˆvalue_1; - if (ˆa_10 === 1) if (is_empty(ˆa_11)) { + const [ˆa_9, ...ˆa_10] = ˆvalue_1; + if (ˆa_9 === 1) if (is_empty(ˆa_10)) { ni; break ˆmatch_2; } } if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { - const [ˆa_12, ...ˆa_13] = ˆvalue_1; - if (ˆa_12 === 1) if (1 < length(ˆa_13)) { + const [ˆa_11, ...ˆa_12] = ˆvalue_1; + if (ˆa_11 === 1) if (1 < length(ˆa_12)) { ni; break ˆmatch_2; } @@ -220,12 +213,17 @@ exports[`match iterables matches values 1`] = ` } } + // TODO: fix semantics for matching [], {} if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { const [ˆa_7, ˆa_8, ˆa_9, ˆa_10] = ˆvalue_1; - if (ˆa_7 === 1) if (ˆa_8 === 2) if (typeof ˆa_9?.[Symbol.iterator] === \\"function\\") if (ˆa_10 != null) { - foo; - break ˆmatch_2; - } + // TODO: fix semantics for matching [], {} + if (ˆa_7 === 1) // TODO: fix semantics for matching [], {} + if (ˆa_8 === 2) // TODO: fix semantics for matching [], {} + if (typeof ˆa_9?.[Symbol.iterator] === \\"function\\") // TODO: fix semantics for matching [], {} + if (ˆa_10 != null) { + foo; + break ˆmatch_2; + } } if (typeof ˆvalue_1?.[Symbol.iterator] === \\"function\\") { @@ -302,14 +300,15 @@ exports[`match matches value assertions 1`] = ` break ˆmatch_2; } - if (ˆvalue_1()) { + // simple as call arg + if (shrub(ˆvalue_1)) { ni; break ˆmatch_2; } - // simple as call arg - if (shrub(ˆvalue_1)) { - ni; + // any value + if (ˆvalue_1 !== undefined) { + true; break ˆmatch_2; } } @@ -424,22 +423,26 @@ exports[`match records matches props 1`] = ` ˆmatch_2: { const ˆvalue_1 = shrub; + // TODO: fix semantics for matching {} if (ˆvalue_1 != null) { const { foo: ˆp_3 } = ˆvalue_1; + // TODO: fix semantics for matching {} if (ˆp_3 != null) { spam + ni; break ˆmatch_2; } } + // TODO: fix semantics for matching [] if (ˆvalue_1 != null) { const { foo: ˆp_4 } = ˆvalue_1; + // TODO: fix semantics for matching [] if (typeof ˆp_4?.[Symbol.iterator] === \\"function\\") { spam + ni; break ˆmatch_2; @@ -587,49 +590,38 @@ exports[`match records matches value assertions 1`] = ` } } - if (ˆvalue_1 != null) { - const { - spam: ˆp_6 - } = ˆvalue_1; - - if (ˆp_6()) { - ni; - break ˆmatch_2; - } - } - // nested member call if (ˆvalue_1 != null) { const { - spam: ˆp_7 + spam: ˆp_6 } = ˆvalue_1; // nested member call - if (ˆp_7.is_foo()) { + if (ˆp_6.is_foo()) { ni; break ˆmatch_2; } } + // nested as call arg if (ˆvalue_1 != null) { const { - spam: ˆp_8 + spam: ˆp_7 } = ˆvalue_1; - if (ˆp_8.is_foo()) { + // nested as call arg + if (is_foo(ˆp_7)) { ni; break ˆmatch_2; } } - // nested as call arg if (ˆvalue_1 != null) { const { - spam: ˆp_9 + spam: ˆp_8, + ...ˆp_9 } = ˆvalue_1; - - // nested as call arg - if (is_foo(ˆp_9)) { + if (ˆp_8 === spam) if (is_empty(ˆp_9)) { ni; break ˆmatch_2; } @@ -640,19 +632,21 @@ exports[`match records matches value assertions 1`] = ` spam: ˆp_10, ...ˆp_11 } = ˆvalue_1; - if (ˆp_10 === spam) if (is_empty(ˆp_11)) { + if (ˆp_10 === spam) if (_in_(\`foo\`, ˆp_11)) { ni; break ˆmatch_2; } } + // any value if (ˆvalue_1 != null) { const { - spam: ˆp_12, - ...ˆp_13 + spam: ˆp_12 } = ˆvalue_1; - if (ˆp_12 === spam) if (_in_(\`foo\`, ˆp_13)) { - ni; + + // any value + if (ˆp_12 !== undefined) { + true; break ˆmatch_2; } } diff --git a/src/lang/func/init.test.fnk b/src/lang/func/init.test.fnk index b6c2d7a..b2149ec 100644 --- a/src/lang/func/init.test.fnk +++ b/src/lang/func/init.test.fnk @@ -47,7 +47,6 @@ describe 'func', fn: fink2js ' fun = fn a, b=12, c: shrub ...a - foo () bar _ ' to_match_snapshot diff --git a/src/lang/func/init.test.fnk.snap b/src/lang/func/init.test.fnk.snap index 29234af..6af10a2 100644 --- a/src/lang/func/init.test.fnk.snap +++ b/src/lang/func/init.test.fnk.snap @@ -3,7 +3,6 @@ exports[`func compiles defaults 1`] = ` "export const fun = (a, b = 12, c) => { shrub(...a); - foo(); return bar(); };" `; diff --git a/src/lang/js-compat/try.test.fnk b/src/lang/js-compat/try.test.fnk index a22e4af..9f3fe37 100644 --- a/src/lang/js-compat/try.test.fnk +++ b/src/lang/js-compat/try.test.fnk @@ -9,7 +9,7 @@ describe 'try', fn: fink2js " foo1 = fn: [err, item] = try: - bar = shrub () + bar = shrub _ bar + ni _ [item, err] diff --git a/src/lang/literals/list.test.fnk b/src/lang/literals/list.test.fnk index 46b95d4..76c35eb 100644 --- a/src/lang/literals/list.test.fnk +++ b/src/lang/literals/list.test.fnk @@ -8,7 +8,7 @@ describe 'list', fn: fink2js ' array1 = [] array2 = [1] - array3 = [1, 2, 4, (a ()), (a _), ...b] + array3 = [1, 2, 4, (a _), ...b] array4 = list: a + 1 + 45 + b + c diff --git a/src/lang/literals/list.test.fnk.snap b/src/lang/literals/list.test.fnk.snap index 2d81132..54fc323 100644 --- a/src/lang/literals/list.test.fnk.snap +++ b/src/lang/literals/list.test.fnk.snap @@ -3,7 +3,7 @@ exports[`list compiles 1`] = ` "export const array1 = []; export const array2 = [1]; -export const array3 = [1, 2, 4, a(), a(), ...b]; +export const array3 = [1, 2, 4, a(), ...b]; export const array4 = [a + 1 + 45 + b + c, [1, 2], (3 + 3) * 2];" `;