diff --git a/src/experiments/inlineListFromArray.ts b/src/experiments/inlineListFromArray.ts new file mode 100644 index 0000000..77c63d7 --- /dev/null +++ b/src/experiments/inlineListFromArray.ts @@ -0,0 +1,68 @@ +import ts from 'typescript'; + +// ` +// var _List_Nil = { $: "[]" }; + +// function _List_Cons(hd, tl) { +// return { $: "::", a: hd, b: tl }; +// } + +// var _List_cons = F2(_List_Cons); + +// function _List_fromArray(arr) { +// var out = _List_Nil; +// for (var i = arr.length; i--; ) { +// out = _List_Cons(arr[i], out); +// } +// return out; +// } +// `; +// ` +// _List_fromArray([ +// "a", +// "b", +// "c", +// ]) +// `; + +const LIST_FROM_ARRAY_F_NAME = '_List_fromArray'; +const LIST_NIL_NAME = '_List_Nil'; +const LIST_CONS_F_NAME = '_List_cons'; + +const listNil = ts.createIdentifier(LIST_NIL_NAME); +const listConsCall = ts.createIdentifier(LIST_CONS_F_NAME); + +const appendToFront = ( + expression: ts.Expression, + list: ts.Expression +): ts.Expression => { + return ts.createCall(listConsCall, undefined, [expression, list]); +}; + +export const createInlineListFromArrayTransformer = (): ts.TransformerFactory => context => { + return sourceFile => { + const visitor = (node: ts.Node): ts.VisitResult => { + // detects [exp](..) + if (ts.isCallExpression(node)) { + const expression = node.expression; + // detects _List_fromArray(..) + if ( + ts.isIdentifier(expression) && + expression.text === LIST_FROM_ARRAY_F_NAME && + node.arguments.length === 1 + ) { + const [arrayLiteral] = node.arguments; + + // detects _List_fromArray([..]) + if (ts.isArrayLiteralExpression(arrayLiteral)) { + return arrayLiteral.elements.reduceRight(appendToFront, listNil); + } + } + } + + return ts.visitEachChild(node, visitor, context); + }; + + return ts.visitNode(sourceFile, visitor); + }; +}; diff --git a/src/index.ts b/src/index.ts index c7b8aed..53e31f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,8 @@ import { createFuncInlineTransformer, } from './experiments/inlineWrappedFunctions'; +import { createInlineListFromArrayTransformer } from './experiments/inlineListFromArray'; + const elmOutput = ` var $elm$core$Maybe$Nothing = {$: 'Nothing'}; @@ -22,6 +24,8 @@ var $author$project$Main$Three = F3( }); var _v1 = A3($author$project$Main$Three, a, b, c); + +_List_fromArray(['a', 'b', 'c']); `; const source = ts.createSourceFile('elm.js', elmOutput, ts.ScriptTarget.ES2018); @@ -68,10 +72,21 @@ const [sourceWithSplittedFunctions] = ts.transform(newFile, [ console.log(printer.printFile(sourceWithSplittedFunctions)); console.log(collectedSplits); -console.log('----------AFTER SPLIT TRANSFORM ----------------'); +console.log('----------AFTER INLINE A(n) TRANSFORM ----------------'); const funcInlineTransformer = createFuncInlineTransformer(collectedSplits); const [sourceWithInlinedFuntioncs] = ts.transform(sourceWithSplittedFunctions, [ funcInlineTransformer, ]).transformed; console.log(printer.printFile(sourceWithInlinedFuntioncs)); + +console.log( + '----------AFTER INLINE _List_fromArray TRANSFORM ----------------' +); +const inlineListFromArrayCalls = createInlineListFromArrayTransformer(); +const [sourceWithInlinedListFromArr] = ts.transform( + sourceWithInlinedFuntioncs, + [inlineListFromArrayCalls] +).transformed; + +console.log(printer.printFile(sourceWithInlinedListFromArr));