Skip to content

Commit

Permalink
feat: AST -> IR -> Optimize -> JS
Browse files Browse the repository at this point in the history
Intorduced an intermediate representation to make it easier to optimize and transform code.

  BREAKING CHANGE: semantics for partial placeholder `?` are in limbo and incompatible with prev versions.
  • Loading branch information
kollhof committed Sep 19, 2021
1 parent 31d7d54 commit c094d0c
Show file tree
Hide file tree
Showing 86 changed files with 2,824 additions and 3,581 deletions.
22 changes: 11 additions & 11 deletions src/generate.fnk
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@ babel_traverse = import '@babel/traverse'
{transformFromAstSync} = import '@babel/core'
{try_catch} = import '@fink/js-interop/errors.fnk'

{transform} = import './js/transform.fnk'
{init_ctx} = import './js/init.fnk'

{transform_do_expr} = import './js/do-expression.fnk'
{transform_async} = import './js/async.fnk'
{module_transforms} = import './js/module.fnk'
{transform_tail_call} = import './js/tail-call.fnk'

{transform} = import './ir/transform.fnk'
{init_ctx} = import './ir/init.fnk'
{optimize} = import './optimize/init.fnk'
{transform_ir} = import './js/init.fnk'
{module_transforms} = import './js/module/init.fnk'
{transform_async} = import './js/async/init.fnk'


transform_file = fn fink_ast, code, filename, options:
ctx = init_ctx code, filename, options

[error, [js_ast]=[]] = try_catch fn:
transform fink_ast, ctx
[lir] = transform fink_ast, 'mod', ctx
[olir] = optimize lir, options
{js} = transform_ir olir, options
[js]

extras = match options:
{module_type: 'cjs'}: module_transforms
Expand All @@ -27,9 +28,7 @@ transform_file = fn fink_ast, code, filename, options:
match error:
false:
traverse js_ast, rec:
DoExpression: transform_do_expr
AwaitExpression: {enter: transform_async}
ArrowFunctionExpression: {exit: transform_tail_call}
...extras

{...js_ast, errors: []}
Expand Down Expand Up @@ -67,3 +66,4 @@ generate = fn ast, filename, source, options={}:
{code: '', source_map: '', errors: js_ast.errors}
else:
babel_generate js_ast, filename, source, options

23 changes: 21 additions & 2 deletions src/generate.test.fnk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{describe, it, expect, to_equal, to_match_snapshot} = import '@fink/jest/test.fnk'
{only, 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'
Expand Down Expand Up @@ -35,7 +35,26 @@ describe 'module types', fn:



describe 'errors', fn:
only.describe 'source maps', fn:
code = "
foo = 12345
bar = 'foo'
ham = 'foo: \${foo} bar:\${bar}'
ni = spam + foo-bar
a = [1, 'ni']
[b, c] = a
out = [a, b, c]
"
js = fink2js code, {module_type: 'mjs', source_maps: 'inline'}

it 'compiles to mjs', fn:
expect
js
to_match_snapshot



skip.describe 'errors', fn:
it 'handles parse errors', fn:
{errors: [{error}]} = fink2js '
foo = ['
Expand Down
56 changes: 36 additions & 20 deletions src/generate.test.fnk.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,51 @@
exports[`module types compiles to cjs 1`] = `
"require(\\"foobar\\");
const foo = require(\\"shrub\\");
const foo_0 = require(\\"shrub\\");
const {
bar: spam,
ni
bar: spam_0
} = require(\\"ni\\");
// reserved words import
const {
default: dflt,
ˆif
ni: ni_0
} = require(\\"ni\\");
const {
ˆdefault: dflt_0
} = require(\\"es6-module\\");
const shrub = ni;
exports.shrub = shrub;
// reserved export
const ˆcase = ni;
exports.ˆcase = ˆcase;
exports.default = shrub;"
const {
ˆif: if_0
} = require(\\"es6-module\\");"
`;

exports[`module types compiles to mjs 1`] = `
"import \\"foobar\\";
import foo from \\"shrub\\";
import { bar as spam, ni } from \\"ni\\";
// reserved words import
import { default as dflt, ˆif } from \\"es6-module\\";
export const shrub = ni;
// reserved export
export const ˆcase = ni;
export default shrub;"
import foo_0 from \\"shrub\\";
import { bar as spam_0 } from \\"ni\\";
import { ni as ni_0 } from \\"ni\\";
import { ˆdefault as dflt_0 } from \\"es6-module\\";
import { ˆif as if_0 } from \\"es6-module\\";
export const shrub = ni_0,
ˆcase = ni_0,
ˆdefault = ni_0;"
`;

exports[`source maps compiles to mjs 1`] = `
"const foo_0 = 12345;
const str_0 = \`foo\`;
const ham_0 = \`foo: \${foo_0} bar:\${str_0}\`;
const ni_0 = spam + fooᜭbar;
const item_1 = 1;
const str_4 = \`ni\`;
const a_0 = [item_1, str_4];
const out_0 = [a_0, item_1, str_4];
export const foo = foo_0,
bar = str_0,
ham = ham_0,
ni = ni_0,
a = a_0,
out = out_0;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QuZm5rIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Y0FDTyxLO2NBQ0EsUUFBRCxLQUFZLFFBQVosS0FBc0IsRTthQUN2QixjOztjQUNJLEkiLCJzb3VyY2VzQ29udGVudCI6WyJmb28gPSAxMjM0NVxuYmFyID0gJ2ZvbydcbmhhbSA9ICdmb286ICR7Zm9vfSBiYXI6JHtiYXJ9J1xubmkgPSBzcGFtICsgZm9vLWJhclxuYSA9IFsxLCAnbmknXVxuW2IsIGNdID0gYVxub3V0ID0gW2EsIGIsIGNdXG4iXX0="
`;
File renamed without changes.
45 changes: 9 additions & 36 deletions src/js/arithmitic/init.fnk
Original file line number Diff line number Diff line change
@@ -1,42 +1,15 @@
babel_types = import '@babel/types'
{binaryExpression, unaryExpression} = babel_types
{add} = import '../context.fnk'

{add, any} = import '../context.fnk'
{transform_binary, transform_binary_or_unary} = import '../transform.fnk'

{transform_with_partial_lr, transform_with_partial} = import '../partial/init.fnk'



transform_op = rec:
'^': '**'



transform_arithmitic = fn {op, left, right}, ctx:
{(op): operator=op} = transform_op

[left_js, right_js, next_ctx, wrap_partial] = transform_with_partial_lr left, right, ctx

js = binaryExpression operator, left_js, right_js

wrap_partial js, next_ctx





transform_unary = fn {op, right}, ctx:
[wrap_partial, right_js, next_ctx] = transform_with_partial right, ctx

js = unaryExpression op, right_js

wrap_partial js, next_ctx



add_arithmitic = fn ctx:
add_arithmitic= fn ctx:
pipe ctx:
add 'arithm', any, transform_arithmitic
add 'arithm:right', any, transform_arithmitic
add 'arithm:prefix', any, transform_unary
add '+', transform_binary
add '-', transform_binary_or_unary
add '*', transform_binary
add '/', transform_binary
add '^', transform_binary
add '%', transform_binary

4 changes: 2 additions & 2 deletions src/js/arithmitic/init.test.fnk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{skip, describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk'
{fink2js} = import '../../testing/generate.fnk'
{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk'


describe 'binary', fn:
Expand All @@ -20,7 +20,7 @@ describe 'binary', fn:
to_match_snapshot


it 'compiles as partial', fn:
skip.it 'compiles as partial', fn:
expect
fink2js '
add = a + ?
Expand Down
15 changes: 10 additions & 5 deletions src/js/arithmitic/init.test.fnk.snap
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`binary compiles 1`] = `
"export const math_precedence1 = -1 + 0 + 1 + 2 * (3 % 1);
export const math_precedence2 = -1 + 0 + (1 + 2) * (3 / 2);
export const multi_line_assign = 123 + 234 + (-567 - 1111);
export const group1 = (1 + 2) * 3;
export const group2 = 34234 ** -34234 + 1;"
"const math_precedence1_0 = -1 + 0 + 1 + 2 * (3 % 1);
const math_precedence2_0 = -1 + 0 + (1 + 2) * (3 / 2);
const multi_line_assign_0 = 123 + 234 + (-567 - 1111);
const group1_0 = (1 + 2) * 3;
const group2_0 = 34234 ** -34234 + 1;
export const math_precedence1 = math_precedence1_0,
math_precedence2 = math_precedence2_0,
multi_line_assign = multi_line_assign_0,
group1 = group1_0,
group2 = group2_0;"
`;

exports[`binary compiles as partial 1`] = `
Expand Down
Loading

0 comments on commit c094d0c

Please sign in to comment.