This commit is contained in:
mdgriffith 2020-07-29 08:49:22 -04:00
commit c26a70f0d7
12 changed files with 41264 additions and 7110 deletions

View File

@ -21,9 +21,7 @@
},
"peerDependencies": {},
"husky": {
"hooks": {
"pre-commit": "tsdx lint"
}
"hooks": {}
},
"prettier": {
"printWidth": 80,
@ -47,4 +45,4 @@
"tree-sitter-elm": "^2.7.9",
"ts-union": "^2.2.1"
}
}
}

View File

@ -1,4 +1,4 @@
import { compile } from 'node-elm-compiler';
import { compileSync } from 'node-elm-compiler';
import * as fs from 'fs';
import * as path from 'path';
import { parseElm } from './parseElm';
@ -20,78 +20,90 @@ import {
convertFunctionExpressionsToArrowFuncs,
} from './experiments/modernizeJS';
// Compile examples in `testcases/*` folder as js
// Run whatever transformations we want on them, saving steps as `elm.{transformation}.js`
compile(['Main.elm'], {
output: 'output/elm.js',
cwd: 'testcases/simple',
});
compile(['Main.elm'], {
output: 'output/elm.opt.js',
cwd: 'testcases/simple',
optimize: true,
});
const pathInOutput = (p: string) => path.join('./testcases/simple/output', p);
const compileAndTransform = (dir: string, file: string): {} => {
const elmSource = fs.readFileSync('./testcases/simple/Main.elm', 'utf8');
// Compile examples in `testcases/*` folder as js
// Run whatever transformations we want on them, saving steps as `elm.{transformation}.js`
compileSync([file], {
output: 'output/elm.js',
cwd: dir,
});
const parsedVariants = parseElm({
author: 'author',
project: 'project',
source: elmSource,
});
compileSync([file], {
output: 'output/elm.opt.js',
cwd: dir,
optimize: true,
});
console.log('11', parsedVariants);
console.log('33', JSON.stringify(parsedVariants, null, 2));
const pathInOutput = (p: string) => path.join(dir, 'output', p);
const source = ts.createSourceFile(
'elm.js',
fs.readFileSync(pathInOutput('elm.opt.js'), 'utf-8'),
ts.ScriptTarget.ES2018
);
const elmSource = fs.readFileSync(path.join(dir, file), 'utf8');
const parsedVariants = parseElm({
author: 'author',
project: 'project',
source: elmSource,
});
const replacements = Object.values(parsedVariants).flat();
// console.log('11', parsedVariants);
// console.log('33', JSON.stringify(parsedVariants, null, 2));
const customTypeTransformer = createCustomTypesTransformer(
replacements,
Mode.Prod
);
const source = ts.createSourceFile(
'elm.js',
fs.readFileSync(pathInOutput('elm.opt.js'), 'utf-8'),
ts.ScriptTarget.ES2018
);
const collectedSplits = new Map<string, FuncSplit>();
const splitTransformer = createSplitFunctionDeclarationsTransformer(
collectedSplits
);
const replacements = Object.values(parsedVariants).flat();
const funcInlineTransformer = createFuncInlineTransformer(collectedSplits);
const customTypeTransformer = createCustomTypesTransformer(
replacements,
Mode.Prod
);
const inlineListFromArrayCalls = createInlineListFromArrayTransformer(
InlineMode.UsingLiteralObjects(Mode.Prod)
);
const collectedSplits = new Map<string, FuncSplit>();
const splitTransformer = createSplitFunctionDeclarationsTransformer(
collectedSplits
);
const [result] = ts.transform(source, [
customTypeTransformer,
splitTransformer,
funcInlineTransformer,
inlineListFromArrayCalls,
replaceUtilsUpdateWithObjectSpread,
convertFunctionExpressionsToArrowFuncs,
]).transformed;
const funcInlineTransformer = createFuncInlineTransformer(collectedSplits);
const printer = ts.createPrinter();
const inlineListFromArrayCalls = createInlineListFromArrayTransformer(
InlineMode.UsingLiteralObjects(Mode.Prod)
);
fs.writeFileSync(
pathInOutput('elm.opt.transformed.js'),
printer.printFile(result)
);
const [result] = ts.transform(source, [
customTypeTransformer,
splitTransformer,
// funcInlineTransformer,
inlineListFromArrayCalls,
replaceUtilsUpdateWithObjectSpread,
const initialJs = ts.createSourceFile(
'elm.js',
fs.readFileSync(pathInOutput('elm.opt.js'), 'utf-8'),
ts.ScriptTarget.ES2018
);
// Arrow functions are disabled because somethings not quite right with them.
// convertFunctionExpressionsToArrowFuncs,
]).transformed;
fs.writeFileSync(pathInOutput('elm.opt.js'), printer.printFile(initialJs));
const printer = ts.createPrinter();
console.log('done!');
fs.writeFileSync(
pathInOutput('elm.opt.transformed.js'),
printer.printFile(result)
);
const initialJs = ts.createSourceFile(
'elm.js',
fs.readFileSync(pathInOutput('elm.opt.js'), 'utf-8'),
ts.ScriptTarget.ES2018
);
fs.writeFileSync(pathInOutput('elm.opt.js'), printer.printFile(initialJs));
console.log('done!');
return {}
}
compileAndTransform('testcases/simple', 'Main.elm')
compileAndTransform('testcases/bench', 'Main.elm')

View File

@ -7,6 +7,58 @@ import { ElmVariant } from './types';
const elmParser = new Parser();
elmParser.setLanguage(Elm);
// List variants
const nil: ElmVariant = {
typeName: "List",
name: "Nil",
jsName: "_List_Nil",
index: 0,
slots: [],
totalTypeSlotCount: 2
}
const cons: ElmVariant = {
typeName: "List",
name: "Cons",
jsName: "_List_Nil",
index: 1,
slots: [],
totalTypeSlotCount: 2
}
const listVariants =
[nil
// , cons
]
// Maybe variants
const nothing: ElmVariant = {
typeName: "Maybe",
name: "Nothing",
jsName: "$elm$core$Maybe$Nothing",
index: 1,
slots: [],
totalTypeSlotCount: 1
}
const just: ElmVariant = {
typeName: "Maybe",
name: "Just",
jsName: "$elm$core$Maybe$Just",
index: 0,
slots: [],
totalTypeSlotCount: 1
}
const maybe = [nothing]
export const parseElm = ({
author,
project,
@ -17,7 +69,7 @@ export const parseElm = ({
source: string;
}): { [id: string]: ElmVariant[] } => {
const tree = elmParser.parse(source);
const found: { [id: string]: ElmVariant[] } = {};
const found: { [id: string]: ElmVariant[] } = { "List": listVariants, "Maybe": maybe };
/*
A quick reference for using treesitter.
@ -138,11 +190,3 @@ export const parseElm = ({
}
return found;
};
const result = parseElm({
author: 'author',
project: 'project',
source: './testcases/simple/Main.elm',
});
console.log(result);

71
testcases/bench/Main.elm Normal file
View File

@ -0,0 +1,71 @@
module Main exposing (main)
{-| -}
import Benchmark exposing (..)
import Benchmark.Runner exposing (BenchmarkProgram, program)
import Html
type MyType
= Zero
| One Int
| Two String String
values =
[ Zero
, One 5
, Two "Two" "two"
]
many =
List.repeat 1000 values
|> List.concat
addMyType mine sum =
case mine of
Zero ->
sum
One i ->
i + sum
Two _ _ ->
sum
type alias MyRecord =
{ one : Int
, two : Int
, three : Int
}
main : BenchmarkProgram
main =
Benchmark.Runner.program suite
updateRecord attr record =
{ record | one = 87 }
suite : Benchmark
suite =
describe "Benchmarks"
[
benchmark "sum 1000 entities in a list" <|
\_ -> List.foldl addMyType 0 many
, benchmark "1000 record updates" <|
\_ -> List.foldl updateRecord
{ one = 1
, two = 2
, three = 3
}
many
]

29
testcases/bench/elm.json Normal file
View File

@ -0,0 +1,29 @@
{
"type": "application",
"source-directories": [
"."
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm-explorations/benchmark": "1.0.1"
},
"indirect": {
"BrianHicks/elm-trend": "2.1.3",
"Skinney/murmur3": "2.0.8",
"elm/json": "1.1.3",
"elm/regex": "1.0.0",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.2",
"mdgriffith/style-elements": "5.0.1"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

14845
testcases/bench/output/elm.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<script src="output/elm.opt.js"></script>
</head>
<body>
<div id="myapp"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById('myapp')
});
</script>
</body>
</html>

View File

@ -0,0 +1,18 @@
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<script src="output/elm.opt.transformed.js"></script>
</head>
<body>
<div id="myapp"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById('myapp')
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff