mirror of
https://github.com/mdgriffith/elm-optimize-level-2.git
synced 2024-12-01 19:35:08 +03:00
233 lines
5.4 KiB
TypeScript
233 lines
5.4 KiB
TypeScript
import ts from 'typescript';
|
|
|
|
import { createFunctionInlineTransformer } from '../src/transforms/inlineWrappedFunctions';
|
|
|
|
test('it can process nested calls of A2 with non identifiers as the first arg ', () => {
|
|
const initialCode = `
|
|
var _VirtualDom_map = F2(function (tagger, node) {
|
|
return {
|
|
$: 4,
|
|
j: tagger,
|
|
k: node,
|
|
b: 1 + (node.b || 0),
|
|
};
|
|
});
|
|
|
|
var $elm$virtual_dom$VirtualDom$map = _VirtualDom_map;
|
|
|
|
A2($elm$virtual_dom$VirtualDom$map, fn, A2(styled.d9, add, context));
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var _VirtualDom_map_fn = function (tagger, node) {
|
|
return {
|
|
$: 4,
|
|
j: tagger,
|
|
k: node,
|
|
b: 1 + (node.b || 0),
|
|
};
|
|
}, _VirtualDom_map = F2(_VirtualDom_map_fn);
|
|
|
|
var $elm$virtual_dom$VirtualDom$map = _VirtualDom_map;
|
|
_VirtualDom_map_fn(fn, A2(styled.d9, add, context));
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
|
|
test('it can process partial application inlining', () => {
|
|
const initialCode = `
|
|
var func = F3(function (a, b, c) {
|
|
return a + b + c;
|
|
});
|
|
|
|
var partialFunc = func(1);
|
|
var partialFunc2 = A2(func, 1, 2);
|
|
|
|
var res = A2(partialFunc, 2, 3);
|
|
var res2 = partialFunc2(3)
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var func_fn = function (a, b, c) {
|
|
return a + b + c;
|
|
}, func = F3(func_fn);
|
|
|
|
var partialFunc_a0 = 1,
|
|
partialFunc = func(partialFunc_a0);
|
|
|
|
var partialFunc2_a0 = 1,
|
|
partialFunc2_a1 = 2,
|
|
partialFunc2 = A2(func, partialFunc2_a0, partialFunc2_a1);
|
|
|
|
var res = func_fn(partialFunc_a0, 2, 3);
|
|
var res2 = func_fn(partialFunc2_a0, partialFunc2_a1, 3);
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
|
|
test('it can inline functions that were wrapped by other functions', () => {
|
|
const initialCode = `
|
|
var func = F2(function (a, b) {
|
|
return F2( function (c, d) { a + b + c + d});
|
|
});
|
|
|
|
var fullyApplied = A2(func, 1, 2);
|
|
|
|
var res = A2(fullyApplied, 3, 4);
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var func_fn = function (a, b) {
|
|
return F2(function (c, d) { a + b + c + d});
|
|
}, func = F2(func_fn);
|
|
|
|
var fullyApplied = func_fn(1, 2), fullyApplied_fn = fullyApplied.f;
|
|
|
|
var res = fullyApplied_fn(3, 4);
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
|
|
test('it can inline functions that were wrapped by other functions even if they are defined separately', () => {
|
|
const initialCode = `
|
|
var raw = function (a, b) {
|
|
return F2( function (c, d) { a + b + c + d});
|
|
}
|
|
|
|
var func = F2(raw);
|
|
|
|
var fullyApplied = A2(func, 1, 2);
|
|
|
|
var res = A2(fullyApplied, 3, 4);
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var raw = function (a, b) {
|
|
return F2( function (c, d) { a + b + c + d});
|
|
}
|
|
|
|
var func = F2(raw);
|
|
|
|
var fullyApplied = raw(1, 2),
|
|
fullyApplied_fn = fullyApplied.f;
|
|
|
|
var res = fullyApplied_fn(3, 4);
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
|
|
test('it can inline functions that were wrapped by other functions even if they are partially applied', () => {
|
|
const initialCode = `
|
|
|
|
var func = F2(function (a, b) {
|
|
return F2( function (c, d) { a + b + c + d});
|
|
});
|
|
|
|
var partiallyApplied = func(1);
|
|
var fullyApplied = partiallyApplied(2);
|
|
|
|
var res = A2(fullyApplied, 3, 4);
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var func_fn = function (a, b) {
|
|
return F2(function (c, d) { a + b + c + d});
|
|
}, func = F2(func_fn);
|
|
|
|
var partiallyApplied_a0 = 1,
|
|
partiallyApplied = func(partiallyApplied_a0);
|
|
|
|
var fullyApplied = func_fn(partiallyApplied_a0, 2),
|
|
fullyApplied_fn = fullyApplied.f;
|
|
|
|
var res = fullyApplied_fn(3, 4);
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
|
|
test('it can inline functions declared not via an identifier or lambda', () => {
|
|
const initialCode = `
|
|
var pow = F2(Math.pow);
|
|
|
|
var res = A2(pow, 2, 3);
|
|
`;
|
|
|
|
const expectedOutputCode = `
|
|
var pow_fn = Math.pow, pow = F2(pow_fn);
|
|
|
|
var res = pow_fn(2, 3);
|
|
`;
|
|
|
|
const { actual, expected } = transformCode(
|
|
initialCode,
|
|
expectedOutputCode,
|
|
createFunctionInlineTransformer(false, 'for tests')
|
|
);
|
|
|
|
expect(actual).toBe(expected);
|
|
});
|
|
export function transformCode(
|
|
initialCode: string,
|
|
expectedCode: string,
|
|
transformer: ts.TransformerFactory<ts.SourceFile>
|
|
): {
|
|
actual: string;
|
|
expected: string;
|
|
} {
|
|
const source = ts.createSourceFile(
|
|
'elm.js',
|
|
initialCode,
|
|
ts.ScriptTarget.ES2018
|
|
);
|
|
|
|
const printer = ts.createPrinter();
|
|
|
|
const [output] = ts.transform(source, [transformer]).transformed;
|
|
|
|
const expectedOutput = printer.printFile(
|
|
ts.createSourceFile('elm.js', expectedCode, ts.ScriptTarget.ES2018)
|
|
);
|
|
|
|
const printedOutput = printer.printFile(output);
|
|
|
|
return {
|
|
actual: printedOutput,
|
|
expected: expectedOutput,
|
|
};
|
|
}
|