Compare commits

..

33 commits

Author SHA1 Message Date
01c3fb2282 small bugfixes and cleanup 2024-06-13 20:23:15 +02:00
eb09d691fd Final finishing touches 2024-06-02 21:43:02 +02:00
68b95e1cfd Fixed node comparison bug 2024-06-02 00:19:44 +02:00
ecf79c4462 Added wildcard identifier collision avoidance 2024-05-31 16:41:22 +02:00
953a1fefa2 Finished cleanup 2024-05-31 16:26:18 +02:00
3dd32df2c1 cleanup 2024-05-31 16:09:49 +02:00
cf200730f7 cleanup 2024-05-28 22:33:52 +02:00
fc6a27e58f Fixed a bug in the multiHeadMatcher 2024-05-28 22:33:52 +02:00
6313ac889c Removed testing files 2024-05-28 22:33:52 +02:00
b4c4540f0b Made transformations literally 10000x faster 2024-05-28 22:33:52 +02:00
f7d7b1c6d3 optimized transformer and created evaluation 2024-05-28 22:33:51 +02:00
7a1f099b33 Changed from * to + 2024-05-28 22:33:51 +02:00
bb3cafb476 Basically finito, needs some final polishing and writing a README 2024-05-28 22:33:51 +02:00
be7905fe1b Almost finito, just missing adding the * 2024-05-28 22:33:51 +02:00
7f3580f15a added boolean logic on the DSL types :) 2024-05-28 22:33:51 +02:00
b1a3ece8f1 idk dude, something is very bad with the transformation 2024-05-28 22:33:51 +02:00
b9cd5a1de9 cleanup 2024-05-28 22:33:51 +02:00
2f3c35462b IT WORKS 2024-05-28 22:33:51 +02:00
8ddffdf3d7 Finished up Langium stuffs and more more more 2024-05-28 22:33:51 +02:00
f2e7912f0b wow, been a long time since i commited to github :) 2024-05-28 22:33:51 +02:00
e482f9b0b4 lol 2024-05-28 22:33:51 +02:00
c3c1736e4d starting to be something xDDDDD 2024-05-28 22:33:51 +02:00
163240b9b2 fixed babel submodule setup 2024-05-28 22:33:51 +02:00
66a9685605 removed properly 2024-05-28 22:33:51 +02:00
7c08233e6b removed babel submodule 2024-05-28 22:33:51 +02:00
f74cd5b99f Langium stuff 2024-05-28 22:33:51 +02:00
57440fb01f Initialized Langium, i am however having some issues with it, perhaps writing my own parser is better? 2024-05-28 22:33:51 +02:00
22f4b9e8f1 Removed babel submodule 2024-05-28 22:33:51 +02:00
faecd127d2 Finally working token 2024-05-28 22:33:51 +02:00
f0b7b1ba98 LESSGOOOO Finally i added some stupid custom syntax :) 2024-05-28 22:33:51 +02:00
19b4b86e20 Added submodule babel 2024-05-28 22:33:51 +02:00
ac163abd9d moved to babel 2024-05-28 22:33:51 +02:00
0e7a019308 Something 2024-05-28 22:33:40 +02:00
42 changed files with 916 additions and 612 deletions

3
.gitignore vendored
View file

@ -1,5 +1,4 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
# Logs # Logs
logs logs
@ -167,3 +166,5 @@ dist
.yarn/build-state.yml .yarn/build-state.yml
.yarn/install-state.gz .yarn/install-state.gz
.pnp.\* .pnp.\*
output_testing/

Binary file not shown.

View file

@ -18,26 +18,26 @@ export function registerValidationChecks(services: JstqlServices) {
* Implementation of custom validations. * Implementation of custom validations.
*/ */
export class JstqlValidator { export class JstqlValidator {
validateWildcards(pair: Case, accept: ValidationAcceptor): void { validateWildcards(case_: Case, accept: ValidationAcceptor): void {
try { try {
let validationResultAplTo = validateWildcardAplTo( let validationResultAplTo = validateWildcardAplTo(
collectWildcard(pair.aplTo.apl_to_code.split("")) collectWildcard(case_.aplTo.apl_to_code.split(""))
); );
if (validationResultAplTo.errors.length != 0) { if (validationResultAplTo.errors.length != 0) {
accept("error", validationResultAplTo.errors.join("\n"), { accept("error", validationResultAplTo.errors.join("\n"), {
node: pair.aplTo, node: case_.aplTo,
property: "apl_to_code", property: "apl_to_code",
}); });
} }
let validationResultTraTo = validateWildcardTraTo( let validationResultTraTo = validateWildcardTraTo(
collectWildcard(pair.traTo.transform_to_code.split("")), collectWildcard(case_.traTo.transform_to_code.split("")),
validationResultAplTo.env validationResultAplTo.env
); );
if (validationResultTraTo.length != 0) { if (validationResultTraTo.length != 0) {
accept("error", validationResultTraTo.join("\n"), { accept("error", validationResultTraTo.join("\n"), {
node: pair.traTo, node: case_.traTo,
property: "transform_to_code", property: "transform_to_code",
}); });
} }
@ -75,7 +75,7 @@ function validateWildcardAplTo(wildcards: string[]): ValidationResultAplTo {
} }
if (!types) { if (!types) {
errors.push("No types given for value"); errors.push("No types given for wildcard " + identifier);
} }
} }
return { env, errors }; return { env, errors };

View file

@ -1 +1,58 @@
# didactic-chainsaw # JSTQL JavaScript Transform tool
This tool is created to transform JavaScript based on definitions written in a custom DSL called JSTQL
## JSTQL
This is a DSL created to define proposal transformations using templates. A transformation is defined by two templates, a template of what code snippets to search for **applicable to** and a template of how to transform those snippets **transform to**.
Examples of definitions for proposals can be found in [dsl_files](./dsl_files/)
## Running this project
This project exposes an api in the file [transform/transfrom.ts](./src/transform/transform.ts), which is meant to be used as this library's entry point.
To run this code as a standalone project, a file [index.ts](./index.ts) exists to facilitate running this project.
This project is created using TypeScript, and it is recommended to use [Bun](https://bun.sh/) to compile and run it.
### Building Langium required files
Firstly, building langium is required, this is done by the following:
```sh
# cd into JSTQL
cd JSTQL
# Install dependencies
npm i
# Build langium generated files
npm run langium:generate
# Build final JS source
npm run build
```
### Running a transformation
Now we are ready to run this project with the pipeline on a test JS file:
```sh
# cd into top level
cd ..
# Install dependencies
bun i
# Run an example transformation
bun run index.ts dsl_files/pipeline.jstql test_files/test.js
```
### Arguments of index.ts
Arguments
- First positional is path to JSTQL
- Second positional is path to JS file to transform
- -o is optional output path, if not given path is **./out.js**

BIN
bun.lockb

Binary file not shown.

View file

@ -1,19 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
</style>
</head>
<body>
<h1>Demo site</h1>
<p></p>
</body>
</html>

View file

@ -2,15 +2,15 @@ proposal awaitToPomise{
case single{ case single{
applicable to { applicable to {
"let <<ident:Identifier>> = await <<awaitedExpr: Expression>>; "let <<ident:Identifier>> = await <<awaitedExpr: Expression>>;
<<statements: (Statement && !ReturnStatement)*>> <<statements: (Statement && !ReturnStatement && !ContinueStatement &&!BreakStatement)+>>
return <<returnExpr: Expression>> return <<returnExpr: Expression>>
" "
} }
transform to{ transform to{
"return <<awaitedExpr>>.then((<<ident>>) => { "return <<awaitedExpr>>.then(async <<ident>> => {
<<statements>> <<statements>>
<<returnExpr>> return <<returnExpr>>
});" });"
} }
} }

View file

@ -1,33 +1,32 @@
proposal DoExpression{ proposal DoExpression{
case arrowFunction{ case arrowFunction{
applicable to { applicable to {
"let <<ident:Identifier>> = () => { "(() => {
<<statements: (Statement && !ReturnStatement)*>> <<statements: (Statement && !ReturnStatement)+>>
return <<returnVal : Expression>>; return <<returnVal : Expression>>;
} })();"
"
} }
transform to { transform to {
"let <<ident>> = do { "(do {
<<statements>> <<statements>>
<<returnVal>> <<returnVal>>
}" })"
} }
} }
case immediatelyInvokedUnnamedFunction { case immediatelyInvokedUnnamedFunction {
applicable to { applicable to {
"let <<ident:Identifier>> = function(){ "(function(){
<<statements: (Statement && !ReturnStatement)*>> <<statements: (Statement && !ReturnStatement)+>>
return <<returnVal : Expression>>; return <<returnVal : Expression>>;
}();" })();"
} }
transform to { transform to {
"let <<ident>> = do { "(do {
<<statements>> <<statements>>
<<returnVal>> <<returnVal>>
}" })"
} }
} }
} }

View file

@ -1,16 +0,0 @@
proposal MultiStmt{
case Smthn{
applicable to{
"let <<ident1:Identifier>> = <<funcIdent:Identifier | MemberExpression>>();
let <<ident2:Identifier>> = <<expr:Expression>>;
"
}
transform to {
"const ident2 = () => {
let <<ident1>> = <<funcIdent>>();
return <<expr>>;
}"
}
}
}

View file

@ -1,17 +0,0 @@
proposal Star{
case a {
applicable to {
"let <<ident:Identifier>> = () => {
<<statements: Statement>>
return <<returnVal : Expression>>;
}
"
}
transform to {
"let <<ident>> = do {
<<statements>>
<<returnVal>>
}"
}
}
}

19
dsl_files/test.jstql Normal file
View file

@ -0,0 +1,19 @@
proposal lol {
case a {
applicable to {
"let <<a: Identifier>> = Iterator.from(<<e: Expression>>);
let <<aa: Identifier>> = Iterator.from(<<ee: Expression>>);
let <<bbbb: Identifier>> = function* () {
yield* <<aaa: Identifier>>;
yield* <<aaaa: Identifier>>;
}();"
}
transform to {
"let <<a>> = Iterator.from(<<e>>);
let <<aa>> = Iterator.from(<<ee>>);
let <<bbbb>> = Iterator.concat(<<aaa>>, <<aaaa>>);"
}
}
}

View file

@ -1,10 +0,0 @@
proposal test_single_stmt{
pair one {
applicable to {
"let <<aaaa: Identifier >> = <<bbbb: Expression | Identifier>>"
}
transform to {
"let <<aaaa>> = 1 + <<bbbb>>;"
}
}
}

View file

@ -3,15 +3,19 @@ Wildcard:
Identifier ":" TypeExpr ("*"?) Identifier ":" TypeExpr ("*"?)
TypeExpr: TypeExpr:
BinaryExpr BinaryExpr
| UnaryExpr
| PrimitiveExpr
BinaryExpr: BinaryExpr:
UnaryExpr { Operator PrimitiveExpr }* TypeExpr { Operator TypeExpr }*
UnaryExpr: UnaryExpr:
{UnaryOperator}? PrimitiveExpr {UnaryOperator}? TypeExpr
PrimitiveExpr: PrimitiveExpr:
GroupExpr | Identifier GroupExpr | Identifier
GroupExpr: GroupExpr:
"(" TypeExpr ")" "(" TypeExpr ")"

55
index.ts Normal file
View file

@ -0,0 +1,55 @@
import {
transform,
} from "./src/transform/transform";
import { parseJSTQL } from "./src/langium/langiumRunner";
import { parseArgs } from "util";
const { values: argVals, tokens: positional } = parseArgs({
options: {
o: {
type: "string",
},
},
tokens: true,
allowPositionals: true,
});
const main = async () => {
//transform(selfHostedTransformExampleMultiStmt, codeFromFile);
console.log(positional);
console.log(argVals);
if (!positional) {
throw new Error("Something is wrong with args");
}
if (
!positional[0] &&
positional[0].kind === "positional" &&
!positional[0].value.endsWith(".jstql")
) {
throw new Error("First positional argument is current JSTQL file");
}
if (!positional[1] || !positional[1].value.endsWith(".js")) {
throw new Error(
"Second positional argument is JS code to be transformed"
);
}
const jstql_file = positional[0].value;
const code_file = positional[1].value;
let jstqlString = await Bun.file(jstql_file).text();
let codeString = await Bun.file(code_file).text();
let parsedJSTQL = await parseJSTQL(jstqlString);
for (let proposal of parsedJSTQL) {
let [resultString, matches] = transform(proposal.cases, codeString);
let path = "./out.js";
if (argVals["o"]) {
path = argVals["o"];
}
await Bun.write(path, resultString);
}
};
main();

3
out.js Normal file
View file

@ -0,0 +1,3 @@
let something = Iterator.from([1, 2, 3]);
let someOtherThing = Iterator.from([4, 5, 6]);
let generate = Iterator.concat(something, someOtherThing);

View file

@ -1,94 +0,0 @@
function parse() {
const input = ("input" |> document.getElementById(%)).value;
const data = 32 |> input.slice(%);
const compressedData = data |> decode_base64(%);
const uncompressed = pako.inflate(compressedData, {
to: "string"
});
const json = uncompressed |> JSON.parse(%);
json |> console.log(%);
json |> convertToDesktop(%);
}
function convertToDesktop(json) {
const newValues = {
crb: false,
newClanRaidClassId: 0,
newClanRaidClassLevel: 0,
pendingImmortalSouls: 0,
pendingRaidRubies: 0,
immortalSouls: 0,
lastPurchaseTime: 0,
lastRaidAttemptTimestamp: 0,
lastRaidRewardCheckTimestamp: 0,
shouldShowHZERoster: false,
lastBonusRewardCheckTimestamp: 0
};
const mappedValues = {
rubies: json.rubies / 10 |> Math.round(%)
};
const pcSpecificValues = {
readPatchNumber: "1.0e12",
saveOrigin: "pc"
};
const hash = "7a990d405d2c6fb93aa8fbb0ec1a3b23";
const newData = {
...newValues,
...json,
...mappedValues,
...pcSpecificValues
};
const compressed = pako.deflate(newData |> JSON.stringify(%), {
to: "string"
});
const base64 = compressed |> btoa(%);
const finalSaveString = hash + base64;
("output_output" |> document.getElementById(%)).innerText = finalSaveString;
showOutput();
}
function showOutput() {
("outputs" |> document.getElementById(%)).style.visibility = "visible";
}
function copyOutput() {
const output = "output_output" |> document.getElementById(%);
output.disabled = false;
output.focus();
output.select();
"copy" |> document.execCommand(%);
output.disabled = true;
const successElement = "copy_success_msg" |> document.getElementById(%);
successElement.style.visibility = "visible";
setTimeout(() => successElement.style.visibility = "hidden", 4000);
}
function decode_base64(s) {
let e = {},
i,
k,
v = [],
r = "",
w = String.fromCharCode;
let n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];
for (z in n) {
for (i = n[z][0]; i < n[z][1]; i++) {
i |> w(%) |> v.push(%);
}
}
for (i = 0; i < 64; i++) {
e[v[i]] = i;
}
for (i = 0; i < s.length; i += 72) {
let b = 0,
c,
x,
l = 0,
o = s.substring(i, i + 72);
for (x = 0; x < o.length; x++) {
c = e[x |> o.charAt(%)];
b = (b << 6) + c;
l += 6;
while (l >= 8) {
r += (b >>> (l -= 8)) % 256 |> w(%);
}
}
}
return r;
}

View file

@ -1,100 +0,0 @@
// "fast-glob" and `createTwoFilesPatch` are bundled here since the API uses `micromatch` and `diff` too
import { createTwoFilesPatch } from "diff/lib/patch/create.js";
import fastGlob from "fast-glob";
import * as vnopts from "vnopts";
import * as errors from "./common/errors.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import mockable from "./common/mockable.js";
import { clearCache as clearConfigCache, resolveConfig, resolveConfigFile } from "./config/resolve-config.js";
import * as core from "./main/core.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import * as optionCategories from "./main/option-categories.js";
import { clearCache as clearPluginCache, loadBuiltinPlugins, loadPlugins } from "./main/plugins/index.js";
import { getSupportInfo as getSupportInfoWithoutPlugins, normalizeOptionSettings } from "./main/support.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";
import omit from "./utils/object-omit.js";
import partition from "./utils/partition.js";
/**
* @param {*} fn
* @param {number} [optionsArgumentIndex]
* @returns {*}
*/
function withPlugins(fn, optionsArgumentIndex = 1 // Usually `options` is the 2nd argument
) {
return async (...args) => {
const options = args[optionsArgumentIndex] ?? {};
const {
plugins = []
} = options;
args[optionsArgumentIndex] = {
...options,
plugins: (await Promise.all([loadBuiltinPlugins(),
// TODO: standalone version allow `plugins` to be `prettierPlugins` which is an object, should allow that too
loadPlugins(plugins)])).flat()
};
return fn(...args);
};
}
const formatWithCursor = withPlugins(core.formatWithCursor);
async function format(text, options) {
const {
formatted
} = await formatWithCursor(text, {
...options,
cursorOffset: -1
});
return formatted;
}
async function check(text, options) {
return (await format(text, options)) === text;
}
// eslint-disable-next-line require-await
async function clearCache() {
clearConfigCache();
clearPluginCache();
}
/** @type {typeof getFileInfoWithoutPlugins} */
const getFileInfo = withPlugins(getFileInfoWithoutPlugins);
/** @type {typeof getSupportInfoWithoutPlugins} */
const getSupportInfo = withPlugins(getSupportInfoWithoutPlugins, 0);
// Internal shared with cli
const sharedWithCli = {
errors,
optionCategories,
createIsIgnoredFunction,
formatOptionsHiddenDefaults,
normalizeOptions,
getSupportInfoWithoutPlugins,
normalizeOptionSettings,
vnopts: {
ChoiceSchema: vnopts.ChoiceSchema,
apiDescriptor: vnopts.apiDescriptor
},
fastGlob,
createTwoFilesPatch,
utils: {
isNonEmptyArray,
partition,
omit
},
mockable
};
const debugApis = {
parse: withPlugins(core.parse),
formatAST: withPlugins(core.formatAst),
formatDoc: withPlugins(core.formatDoc),
printToDoc: withPlugins(core.printToDoc),
printDocToString: withPlugins(core.printDocToString),
mockable
};
export { debugApis as __debug, sharedWithCli as __internal, check, clearCache as clearConfigCache, format, formatWithCursor, getFileInfo, getSupportInfo, resolveConfig, resolveConfigFile };
export * as doc from "./document/public.js";
export { default as version } from "./main/version.evaluate.cjs";
export * as util from "./utils/public.js";

View file

@ -1,12 +0,0 @@
let aaaa = do {
let g = 100;
let ff = 10;
let ggg = a(b);
100;
};
let bbaaa = do {
let lllll = 1 + 1;
100 + 100;
const aaaaa = aaaa(bb);
lllll;
};

View file

@ -1,2 +0,0 @@
let ThisTest = LOOOOOOOOL();
let HAHHAHAH = 1 + 1;

View file

@ -1,4 +0,0 @@
a |> w(%) |> w(%) |> w(%) |> w(%) |> w(%) |> w(%) |> w(%) |> w(%) |> w(%) |> w(%);
a |> b(%, a |> b(%, a |> b(%, a |> b(%, a |> b(%, a |> b(%, a |> b(%, b)))))));
a |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a) |> b(%, a);
b(b(b(b(a, a, a), a, a), a, a), a, a);

View file

@ -1,98 +0,0 @@
// "fast-glob" and `createTwoFilesPatch` are bundled here since the API uses `micromatch` and `diff` too
import { createTwoFilesPatch } from "diff/lib/patch/create.js";
import fastGlob from "fast-glob";
import * as vnopts from "vnopts";
import * as errors from "./common/errors.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import mockable from "./common/mockable.js";
import { clearCache as clearConfigCache, resolveConfig, resolveConfigFile } from "./config/resolve-config.js";
import * as core from "./main/core.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import * as optionCategories from "./main/option-categories.js";
import { clearCache as clearPluginCache, loadBuiltinPlugins, loadPlugins } from "./main/plugins/index.js";
import { getSupportInfo as getSupportInfoWithoutPlugins, normalizeOptionSettings } from "./main/support.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";
import omit from "./utils/object-omit.js";
import partition from "./utils/partition.js";
/**
* @param {*} fn
* @param {number} [optionsArgumentIndex]
* @returns {*}
*/
function withPlugins(fn, optionsArgumentIndex = 1 // Usually `options` is the 2nd argument
) {
return async (...args) => {
const options = args[optionsArgumentIndex] ?? {};
const {
plugins = []
} = options;
args[optionsArgumentIndex] = {
...options,
plugins: (await ([loadBuiltinPlugins(), plugins |> loadPlugins(%)] |> Promise.all(%))).flat()
};
return fn(...args);
};
}
const formatWithCursor = core.formatWithCursor |> withPlugins(%);
async function format(text, options) {
const {
formatted
} = await (text |> formatWithCursor(%, {
...options,
cursorOffset: -1
}));
return formatted;
}
async function check(text, options) {
return (await (text |> format(%, options))) === text;
}
// eslint-disable-next-line require-await
async function clearCache() {
clearConfigCache();
clearPluginCache();
}
/** @type {typeof getFileInfoWithoutPlugins} */
const getFileInfo = getFileInfoWithoutPlugins |> withPlugins(%);
/** @type {typeof getSupportInfoWithoutPlugins} */
const getSupportInfo = getSupportInfoWithoutPlugins |> withPlugins(%, 0);
// Internal shared with cli
const sharedWithCli = {
errors,
optionCategories,
createIsIgnoredFunction,
formatOptionsHiddenDefaults,
normalizeOptions,
getSupportInfoWithoutPlugins,
normalizeOptionSettings,
vnopts: {
ChoiceSchema: vnopts.ChoiceSchema,
apiDescriptor: vnopts.apiDescriptor
},
fastGlob,
createTwoFilesPatch,
utils: {
isNonEmptyArray,
partition,
omit
},
mockable
};
const debugApis = {
parse: core.parse |> withPlugins(%),
formatAST: core.formatAst |> withPlugins(%),
formatDoc: core.formatDoc |> withPlugins(%),
printToDoc: core.printToDoc |> withPlugins(%),
printDocToString: core.printDocToString |> withPlugins(%),
mockable
};
export { debugApis as __debug, sharedWithCli as __internal, check, clearCache as clearConfigCache, format, formatWithCursor, getFileInfo, getSupportInfo, resolveConfig, resolveConfigFile };
export * as doc from "./document/public.js";
export { default as version } from "./main/version.evaluate.cjs";
export * as util from "./utils/public.js";

306
package-lock.json generated
View file

@ -15,7 +15,8 @@
"@types/babel-traverse": "^6.25.10", "@types/babel-traverse": "^6.25.10",
"babel": "^6.23.0", "babel": "^6.23.0",
"bun": "^1.0.4", "bun": "^1.0.4",
"ts-node": "^10.9.1" "ts-node": "^10.9.1",
"util": "^0.12.5"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-pipeline-operator": "^7.23.3", "@babel/plugin-proposal-pipeline-operator": "^7.23.3",
@ -1001,6 +1002,21 @@
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
}, },
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/babel": { "node_modules/babel": {
"version": "6.23.0", "version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz", "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
@ -1293,6 +1309,25 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001574", "version": "1.0.30001574",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz",
@ -1452,6 +1487,23 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/diff": { "node_modules/diff": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@ -1474,6 +1526,27 @@
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -1647,6 +1720,24 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"license": "MIT",
"dependencies": {
"is-callable": "^1.1.3"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gensync": { "node_modules/gensync": {
"version": "1.0.0-beta.2", "version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@ -1655,6 +1746,25 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
@ -1684,6 +1794,18 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/got": { "node_modules/got": {
"version": "11.8.6", "version": "11.8.6",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
@ -1717,6 +1839,69 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-cache-semantics": { "node_modules/http-cache-semantics": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@ -1768,8 +1953,35 @@
"node_modules/inherits": { "node_modules/inherits": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"dev": true },
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
}, },
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
@ -1780,6 +1992,21 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"license": "MIT",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": { "node_modules/is-glob": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@ -1819,6 +2046,21 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/is-typed-array": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
"integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
"license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/isexe": { "node_modules/isexe": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -2082,6 +2324,15 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/possible-typed-array-names": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
"integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/pseudomap": { "node_modules/pseudomap": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@ -2291,6 +2542,23 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true "dev": true
}, },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -2559,6 +2827,19 @@
"browserslist": ">= 4.21.0" "browserslist": ">= 4.21.0"
} }
}, },
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -2582,6 +2863,25 @@
"which": "bin/which" "which": "bin/which"
} }
}, },
"node_modules/which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
"integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wrappy": { "node_modules/wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",

View file

@ -20,10 +20,11 @@
"@babel/generator": "^7.23.0", "@babel/generator": "^7.23.0",
"@babel/parser": "^7.23.0", "@babel/parser": "^7.23.0",
"@babel/traverse": "^7.23.0", "@babel/traverse": "^7.23.0",
"@types/babel__traverse": "^7.20.5",
"@types/babel-traverse": "^6.25.10", "@types/babel-traverse": "^6.25.10",
"@types/babel__traverse": "^7.20.5",
"babel": "^6.23.0", "babel": "^6.23.0",
"bun": "^1.0.4", "bun": "^1.0.4",
"ts-node": "^10.9.1" "ts-node": "^10.9.1",
"util": "^0.12.5"
} }
} }

8
src/api/jstqlsh.ts Normal file
View file

@ -0,0 +1,8 @@
import { SelfHostedRecipe } from "../transform/transform";
import { transform } from "../transform/transform";
export function transformSH(spec: SelfHostedRecipe[], code: string) {
let res = transform(spec, code);
return res;
}

66
src/evalRunner.ts Normal file
View file

@ -0,0 +1,66 @@
import { transform } from "./transform/transform";
import { readdir } from "node:fs/promises";
import { parseJSTQL } from "./langium/langiumRunner";
const main = async () => {
let basepathExamplesJSFiles = "../three.js";
let examples = (await readdir(basepathExamplesJSFiles, { recursive: true }))
.filter((x) => x.endsWith(".js"))
.map((x) => basepathExamplesJSFiles + "/" + x);
console.log(examples);
let result = [];
for (let proposalFile of [
"pipeline.jstql",
"do.jstql",
"awaitToPromise.jstql",
]) {
const jstql_file = "dsl_files/" + proposalFile;
const test_file = Bun.file(jstql_file);
const test_JSTQL = await test_file.text();
let proposals = await parseJSTQL(test_JSTQL);
let sum = 0;
let failures = 0;
let filesSucceeded = 0;
console.log("Scripts found ", sum, "matches!");
let count = 0;
for (let examplesFile of examples) {
try {
if (examplesFile.split("/").includes("compiled")) {
//continue;
}
console.log(examplesFile);
let script = await Bun.file(examplesFile).text();
let [resultString, matches] = transform(
proposals[0].cases,
script
);
sum += matches;
console.log(matches);
if (matches > 0) {
await Bun.write(
"output_testing/" +
count +
examplesFile.split("/").join("_"),
resultString
);
count += 1;
}
filesSucceeded += 1;
} catch (e) {
failures += 1;
//console.log(e);
}
console.log("current sum", sum);
}
result.push(
proposalFile + ", " + sum + ", " + count + ", " + filesSucceeded
);
}
for (let res of result) {
console.log(res);
}
};
main();

View file

@ -1,31 +0,0 @@
//import * as babelparser from "../babel/packages/babel-parser";
import * as babelparser from "@babel/parser";
//import core from "../babel/packages/babel-core";
import { parse_with_plugins } from "./parser/parse";
import {
SelfHostedRecipe,
TransformRecipe,
transform,
} from "./transform/transform";
import { parseJSTQL } from "./langium/langiumRunner";
const dir = "../prettier/src";
const path = "../prettier/src/index.js";
const file = Bun.file(path);
const codeFromFile = await file.text();
const main = async () => {
//transform(selfHostedTransformExampleMultiStmt, codeFromFile);
console.log(codeFromFile);
const jstql_file =
"/home/rolfmg/Coding/Master/didactic-chainsaw/dsl_files/pipeline.jstql";
const test_file = Bun.file(jstql_file);
const test_JSTQL = await test_file.text();
let proposals = await parseJSTQL(test_JSTQL);
let code = transform(proposals[0].cases, codeFromFile);
await Bun.write("output_files/testingLOL.js", code);
};
main();

View file

@ -200,17 +200,10 @@ export class Matcher {
return MatchResult.NoMatch; return MatchResult.NoMatch;
} }
} }
for (let key of Object.keys(aplToNode)) {
if (key in keys_to_ignore) {
continue;
}
if (!Object.keys(codeNode).includes(key)) { return codeNode.type === aplToNode.type
return MatchResult.NoMatch; ? MatchResult.Matched
} : MatchResult.NoMatch;
}
return MatchResult.Matched;
} }
multiStatementMatcher(code: TreeNode<t.Node>, aplTo: TreeNode<t.Node>) { multiStatementMatcher(code: TreeNode<t.Node>, aplTo: TreeNode<t.Node>) {
@ -233,7 +226,7 @@ export class Matcher {
let statements: TreeNode<PairedNodes>[] = []; let statements: TreeNode<PairedNodes>[] = [];
let aplToi = 0; let aplToi = 0;
let codei = 0; let codei = 0;
while (aplToi < aplTo.length) { while (aplToi < aplTo.length && codei + y < code.length) {
let [paired, matchResult] = this.exactExprMatcher( let [paired, matchResult] = this.exactExprMatcher(
code[codei + y], code[codei + y],
aplTo[aplToi] aplTo[aplToi]
@ -267,6 +260,9 @@ export class Matcher {
aplToi += 1; aplToi += 1;
codei += 1; codei += 1;
} }
if (aplToi !== aplTo.length) {
fullMatch = false;
}
if (fullMatch) { if (fullMatch) {
this.matches.push({ statements }); this.matches.push({ statements });
} }
@ -324,6 +320,7 @@ export class Matcher {
i -= 1; i -= 1;
break; break;
} }
pairedChild.element.codeNode.push( pairedChild.element.codeNode.push(
...maybeChild.element.codeNode ...maybeChild.element.codeNode
); );
@ -334,6 +331,10 @@ export class Matcher {
i += 1; i += 1;
aplToi += 1; aplToi += 1;
} }
// Verify it is a full match
if (aplToi < aplTo.children.length) {
return [undefined, MatchResult.NoMatch];
}
if (i < code.children.length) { if (i < code.children.length) {
return [undefined, MatchResult.NoMatch]; return [undefined, MatchResult.NoMatch];
} }

View file

@ -24,7 +24,7 @@ export function parseInternalTraTo(code: string): string {
// We encountered a closing tag // We encountered a closing tag
flag = false; flag = false;
cleanedJS += temp; cleanedJS += "_$$_" + temp + "_$$_";
i += 1; i += 1;
temp = ""; temp = "";
@ -59,7 +59,8 @@ export function parseInternalAplTo(code: string): InternalParseResult {
let wildcard = new WildcardParser( let wildcard = new WildcardParser(
new WildcardTokenizer(temp).tokenize() new WildcardTokenizer(temp).tokenize()
).parse(); ).parse();
wildcard.identifier.name =
"_$$_" + wildcard.identifier.name + "_$$_";
cleanedJS += wildcard.identifier.name; cleanedJS += wildcard.identifier.name;
prelude.push(wildcard); prelude.push(wildcard);
@ -76,7 +77,6 @@ export function parseInternalAplTo(code: string): InternalParseResult {
} }
return { prelude, cleanedJS }; return { prelude, cleanedJS };
} }
export interface Identifier extends WildcardNode { export interface Identifier extends WildcardNode {
nodeType: "Identifier"; nodeType: "Identifier";
name: string; name: string;
@ -154,7 +154,7 @@ export class WildcardParser {
let identifier = this.Identifier(); let identifier = this.Identifier();
this.Semicolon(); this.Semicolon();
let multidenoted = this.TypeExpr(); let multidenoted = this.TypeExpr();
let star = this.Star(); let star = this.Pluss();
return { return {
nodeType: "Wildcard", nodeType: "Wildcard",
identifier, identifier,
@ -163,8 +163,8 @@ export class WildcardParser {
}; };
} }
private Star(): boolean { private Pluss(): boolean {
if (this.peek() && this.peek().tokenKind === "Star") { if (this.peek() && this.peek().tokenKind === "Pluss") {
this.advance(); this.advance();
return true; return true;
} else { } else {

View file

@ -19,13 +19,13 @@ function extractValues(types: t.Statement[]): Wildcard[] {
if (init) { if (init) {
if (init.type == "StringLiteral") { if (init.type == "StringLiteral") {
init = <t.StringLiteral>init; init = <t.StringLiteral>init;
prelude.push( let wildcard = new WildcardParser(
new WildcardParser(
new WildcardTokenizer( new WildcardTokenizer(
innerDSLVariableName + ":" + init innerDSLVariableName + ":" + init
).tokenize() ).tokenize()
).parse() ).parse();
);
prelude.push(wildcard);
} else { } else {
throw new Error( throw new Error(
"Invalid usage of right side declaration in prelude" "Invalid usage of right side declaration in prelude"

View file

@ -4,7 +4,7 @@ type TokenKind =
| "Identifier" | "Identifier"
| "OpeningParenthesis" | "OpeningParenthesis"
| "ClosingParenthesis" | "ClosingParenthesis"
| "Star" | "Pluss"
| "Semicolon"; | "Semicolon";
export interface WildcardToken { export interface WildcardToken {
@ -79,8 +79,8 @@ export class WildcardTokenizer {
} }
break; break;
} }
case "*": { case "+": {
this.consumeToken("Star", char); this.consumeToken("Pluss", char);
break; break;
} }
case ":": { case ":": {
@ -116,7 +116,7 @@ export class WildcardTokenizer {
} }
private isAlpha(val: string): boolean { private isAlpha(val: string): boolean {
let alphabet = new Set( let alphabet = new Set(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".split("") "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890".split("")
); );
return alphabet.has(val); return alphabet.has(val);
} }

View file

@ -1,9 +1,9 @@
async function something() { async function something() {
let a = 100; let a = 100;
a *= 100000; a *= 100000;
return fetch("https://uib.no").then(uib => { return fetch("https://uib.no").then(async uib => {
a += 100000; a += 100000;
a -= 1000; a -= 1000;
[a, uib]; return [a, uib];
}); });
} }

View file

@ -2,11 +2,11 @@ let aaaa = do {
let g = 100; let g = 100;
let ff = 10; let ff = 10;
let ggg = a(b); let ggg = a(b);
100; 100
}; };
let bbaaa = do { var bbaaa = do {
let lllll = 1 + 1; let lllll = 1 + 1;
100 + 100; 100 + 100;
const aaaaa = aaaa(bb); const aaaaa = aaaa(bb);
lllll; lllll
}; };

View file

@ -22,23 +22,23 @@ let pipelineResFile = await Bun.file(
"src/test/test_outputs/pipeline_output.js" "src/test/test_outputs/pipeline_output.js"
).text(); ).text();
test("Test code: pipeline", () => { test("Test code: pipeline", () => {
expect(pipelineRes).toBe(pipelineResFile); expect(pipelineRes).toEqual([pipelineResFile, 29]);
}); });
let doRes = await runTest("test_files/do_test.js", "dsl_files/do.jstql"); let doRes = await runTest("test_files/do_test.js", "dsl_files/do.jstql");
let doResFile = await Bun.file("src/test/test_outputs/do_output.js").text(); let doResFile = await Bun.file("src/test/test_outputs/do_output.js").text();
test("Test code: do", () => { test("Test code: do", () => {
expect(doRes).toBe(doResFile); expect(doRes).toEqual([doResFile, 2]);
}); });
let awaitToPromise = await runTest( let awaitToPromise = await runTest(
"test_files/do_test.js", "test_files/awaitToPromise.js",
"dsl_files/do.jstql" "dsl_files/awaitToPromise.jstql"
); );
let awaitToPromiseOutput = await Bun.file( let awaitToPromiseOutput = await Bun.file(
"src/test/test_outputs/do_output.js" "src/test/test_outputs/awaitToPromise_output.js"
).text(); ).text();
test("Test code: do", () => { test("Test code: await to promise", () => {
expect(awaitToPromise).toBe(awaitToPromiseOutput); expect(awaitToPromise).toEqual([awaitToPromiseOutput, 1]);
}); });

View file

@ -28,13 +28,16 @@ export interface TransformRecipe {
export interface SelfHostedRecipe extends TransformRecipe { export interface SelfHostedRecipe extends TransformRecipe {
prelude: string; prelude: string;
} }
export function transform(recipes: TransformRecipe[], code: string): string { export function transform(
recipes: TransformRecipe[],
code: string
): [string, number] {
let codeAST: t.Node = parse_with_plugins(code); let codeAST: t.Node = parse_with_plugins(code);
let amount = 0;
for (let recipe of recipes) { for (let recipe of recipes) {
if ((<SelfHostedRecipe>recipe).prelude !== undefined) { if ((<SelfHostedRecipe>recipe).prelude !== undefined) {
// We are using the self hosted version // We are using the self hosted version
codeAST = transformSelfHosted( let temp = transformSelfHosted(
{ {
applicableTo: recipe.applicableTo, applicableTo: recipe.applicableTo,
transformTo: recipe.transformTo, transformTo: recipe.transformTo,
@ -42,6 +45,8 @@ export function transform(recipes: TransformRecipe[], code: string): string {
preludeBuilder((recipe as SelfHostedRecipe).prelude), preludeBuilder((recipe as SelfHostedRecipe).prelude),
codeAST codeAST
); );
codeAST = temp[0];
amount += temp[1];
} else { } else {
// We are using JSTQL // We are using JSTQL
// We have to parse JSTQL to the self hosted version // We have to parse JSTQL to the self hosted version
@ -51,24 +56,26 @@ export function transform(recipes: TransformRecipe[], code: string): string {
); );
let transformTo = parseInternalTraTo(recipe.transformTo); let transformTo = parseInternalTraTo(recipe.transformTo);
codeAST = transformSelfHosted( let temp = transformSelfHosted(
{ applicableTo, transformTo }, { applicableTo, transformTo },
prelude, prelude,
codeAST codeAST
); );
codeAST = temp[0];
amount += temp[1];
} }
} }
let output = generate(codeAST, { topicToken: "%" }).code; let output = generate(codeAST, { topicToken: "%" }).code;
//showTree(transformToTree); //showTree(transformToTree);
return output; return [output, amount];
} }
function transformSelfHosted( export function transformSelfHosted(
recipe: TransformRecipe, recipe: TransformRecipe,
internals: Wildcard[], internals: Wildcard[],
codeAST: t.Node codeAST: t.Node
): t.Node { ): [t.Node, number] {
let codeTree = makeTree(codeAST as babelparser.ParseResult<t.File>); let codeTree = makeTree(codeAST as babelparser.ParseResult<t.File>);
let applicabelToAST = parse_with_plugins(recipe.applicableTo); let applicabelToAST = parse_with_plugins(recipe.applicableTo);
@ -83,9 +90,9 @@ function transformSelfHosted(
) { ) {
throw new Error("This no worky LOL"); throw new Error("This no worky LOL");
} }
let matches = runMatch(codeTree, applicableToTree, internals); let matches = runMatch(codeTree, applicableToTree, internals);
console.log("We found", matches.length, "matches");
let outputAST = transformer(matches, transformToTree, codeAST, transformTo); let outputAST = transformer(matches, transformToTree, codeAST, transformTo);
return outputAST;
return [outputAST, matches.length];
} }

View file

@ -12,6 +12,7 @@ import { Match, MatchedTreeNode, PairedNodes } from "../matcher/matcher";
import traverse from "@babel/traverse"; import traverse from "@babel/traverse";
import generate from "@babel/generator"; import generate from "@babel/generator";
import { TransformRecipe } from "./transform"; import { TransformRecipe } from "./transform";
import { Wildcard } from "../parser/parse";
export function transformer( export function transformer(
matches: Match[], matches: Match[],
@ -19,57 +20,50 @@ export function transformer(
codeAST: t.Node, codeAST: t.Node,
traToAST: t.File traToAST: t.File
): t.Node { ): t.Node {
let transformedTransformTo: Map<t.Node, [t.File, Match]> = new Map();
for (let match of matches.reverse()) { for (let match of matches.reverse()) {
try { try {
let traToWithWildcards = structuredClone(traToAST); let traToWithWildcards = structuredClone(traToAST);
for (let match_stmt of match.statements) { let wildcardMatches = extractWildcardPairs(match);
transformMatch(match_stmt, transformTo, traToWithWildcards);
transformedTransformTo.set(
match.statements[0].element.codeNode[0],
[
transformMatchFaster(wildcardMatches, traToWithWildcards),
match,
]
);
} catch (e) {
console.log(e);
} }
}
traverse(codeAST, { traverse(codeAST, {
enter(path) { enter(path) {
if ( if (!(path.node.type === "Program" || path.node.type === "File")) {
!( if (transformedTransformTo.has(path.node)) {
path.node.type === "Program" || let [traToWithWildcards, match] =
path.node.type === "File" transformedTransformTo.get(path.node) as [
) t.File,
) { Match
if ( ];
path.node === path.replaceWithMultiple(traToWithWildcards.program.body);
match.statements[0].element.codeNode[0]
) {
path.replaceWithMultiple(
traToWithWildcards.program.body
);
let siblings = path.getAllNextSiblings(); let siblings = path.getAllNextSiblings();
// For multi line applicable to // For multi line applicable to
for ( for (let i = 0; i < match.statements.length - 1; i++) {
let i = 0; //siblings[i].remove();
i < match.statements.length - 1;
i++
) {
siblings[i].remove();
} }
// For when we have matched with * // For when we have matched with +
for (let matchStmt of match.statements) { for (let matchStmt of match.statements) {
for (let [ for (let stmtMatchedWithPlus of matchStmt.element
i, .codeNode) {
stmtMatchedWithStar, let siblingnodes = siblings.map((a) => a.node);
] of matchStmt.element.codeNode.entries()) { if (siblingnodes.includes(stmtMatchedWithPlus)) {
let siblingnodes = siblings.map(
(a) => a.node
);
if (
siblingnodes.includes(
stmtMatchedWithStar
)
) {
let index = let index =
siblingnodes.indexOf( siblingnodes.indexOf(stmtMatchedWithPlus);
stmtMatchedWithStar
);
siblings[index].remove(); siblings[index].remove();
} }
} }
@ -78,73 +72,70 @@ export function transformer(
} }
}, },
}); });
} catch (e) {
console.log(e);
}
}
return codeAST; return codeAST;
} }
export function transformMatch( function transformMatchFaster(
match: TreeNode<PairedNodes>, wildcardMatches: Map<string, t.Node[]>,
trnTo: TreeNode<t.Node>, transformTo: t.File
output: t.Node ): t.File {
) { traverse(transformTo, {
let isMatchingIdentifier = matchNode(
match.element.aplToNode,
trnTo.element
);
if (isMatchingIdentifier) {
traverse(output, {
Identifier: (path) => { Identifier: (path) => {
if (path.node.name === (<t.Identifier>trnTo.element).name) { if (wildcardMatches.has(path.node.name)) {
path.replaceWithMultiple(match.element.codeNode); let toReplaceWith = wildcardMatches.get(path.node.name);
if (toReplaceWith) {
path.replaceWithMultiple(toReplaceWith);
}
} }
}, },
ExpressionStatement: (path) => { ExpressionStatement: (path) => {
if (trnTo.element.type === "ExpressionStatement") { if (path.node.expression.type === "Identifier") {
if ( let name = path.node.expression.name;
path.node.expression.type === "Identifier" && if (wildcardMatches.has(name)) {
trnTo.element.expression.type === "Identifier" let toReplaceWith = wildcardMatches.get(name);
) { if (toReplaceWith) {
let ident = path.node.expression; path.replaceWithMultiple(toReplaceWith);
if (ident.name === trnTo.element.expression.name) {
path.replaceWithMultiple(match.element.codeNode);
} }
} }
} }
}, },
}); });
} else {
for (let match_child of match.children) { return transformTo;
transformMatch(match_child, trnTo, output);
}
for (let trnTo_child of trnTo.children) {
transformMatch(match, trnTo_child, output);
}
}
} }
function matchNode(aplTo: t.Node, trnTo: t.Node): boolean { function extractWildcardPairs(match: Match): Map<string, t.Node[]> {
//console.log(trnTo); let map: Map<string, t.Node[]> = new Map();
if ( function recursiveSearch(node: TreeNode<PairedNodes>) {
trnTo.type === "ExpressionStatement" && let name: null | string = null;
aplTo.type == "ExpressionStatement" if (node.element.aplToNode.type === "Identifier") {
name = node.element.aplToNode.name;
} else if (
node.element.aplToNode.type === "ExpressionStatement" &&
node.element.aplToNode.expression.type === "Identifier"
) { ) {
if ( name = node.element.aplToNode.expression.name;
trnTo.expression.type === "Identifier" &&
aplTo.expression.type === "Identifier"
) {
return aplTo.expression.name === trnTo.expression.name;
}
} }
if (trnTo.type == "Identifier" && aplTo.type == "Identifier") { if (name && name.startsWith("_$$_")) {
return aplTo.name === trnTo.name; if (map.has(name)) {
console.log(name);
console.log(map.get(name));
throw new Error("Wildcard encountered twice!");
} }
return false;
map.set(name, node.element.codeNode);
}
for (let child of node.children) {
recursiveSearch(child);
}
}
for (let stmt of match.statements) {
recursiveSearch(stmt);
}
return map;
} }
function washName(name: string): string { function washName(name: string): string {

View file

@ -1,9 +1,9 @@
let aaaa = () => { let aaaa = (() => {
let g = 100; let g = 100;
let ff = 10; let ff = 10;
let ggg = a(b); let ggg = a(b);
return 100; return 100;
}; })();
var bbaaa = (function () { var bbaaa = (function () {
let lllll = 1 + 1; let lllll = 1 + 1;

View file

@ -1,7 +0,0 @@
let a = LOOOOOOOOL();
let b = (999 * 128) / 12;
const haha = () => {
let a = LOOOOOOOOL();
let b = (999 * 128) / 12;
};

View file

@ -1,8 +0,0 @@
let something = 1 + 1;
let yikers = hahahah;
let lol = () => 100 + 100;
function haha() {
let fhdsjkfhdsjkfhds = fjhdkslfjhdsklfjdskl;
}

View file

@ -1,4 +0,0 @@
let x = () => {
let b = 0;
return b;
};

208
test_files/test2.js Normal file
View file

@ -0,0 +1,208 @@
let _geometry;
const _intersectPoint = /*@__PURE__*/ new Vector3();
const _worldScale = /*@__PURE__*/ new Vector3();
const _mvPosition = /*@__PURE__*/ new Vector3();
const _alignedPosition = /*@__PURE__*/ new Vector2();
const _rotatedPosition = /*@__PURE__*/ new Vector2();
const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
const _vA = /*@__PURE__*/ new Vector3();
const _vB = /*@__PURE__*/ new Vector3();
const _vC = /*@__PURE__*/ new Vector3();
const _uvA = /*@__PURE__*/ new Vector2();
const _uvB = /*@__PURE__*/ new Vector2();
const _uvC = /*@__PURE__*/ new Vector2();
class Sprite extends Object3D {
constructor(material = new SpriteMaterial()) {
super();
this.isSprite = true;
this.type = "Sprite";
if (_geometry === undefined) {
_geometry = new BufferGeometry();
const float32Array = new Float32Array([
-0.5, -0.5, 0, 0, 0, 0.5, -0.5, 0, 1, 0, 0.5, 0.5, 0, 1, 1,
-0.5, 0.5, 0, 0, 1,
]);
const interleavedBuffer = new InterleavedBuffer(float32Array, 5);
_geometry.setIndex([0, 1, 2, 0, 2, 3]);
_geometry.setAttribute(
"position",
new InterleavedBufferAttribute(interleavedBuffer, 3, 0, false)
);
_geometry.setAttribute(
"uv",
new InterleavedBufferAttribute(interleavedBuffer, 2, 3, false)
);
}
this.geometry = _geometry;
this.material = material;
this.center = new Vector2(0.5, 0.5);
}
raycast(raycaster, intersects) {
if (raycaster.camera === null) {
console.error(
'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.'
);
}
_worldScale.setFromMatrixScale(this.matrixWorld);
_viewWorldMatrix.copy(raycaster.camera.matrixWorld);
this.modelViewMatrix.multiplyMatrices(
raycaster.camera.matrixWorldInverse,
this.matrixWorld
);
_mvPosition.setFromMatrixPosition(this.modelViewMatrix);
if (
raycaster.camera.isPerspectiveCamera &&
this.material.sizeAttenuation === false
) {
_worldScale.multiplyScalar(-_mvPosition.z);
}
const rotation = this.material.rotation;
let sin, cos;
if (rotation !== 0) {
cos = Math.cos(rotation);
sin = Math.sin(rotation);
}
const center = this.center;
transformVertex(
_vA.set(-0.5, -0.5, 0),
_mvPosition,
center,
_worldScale,
sin,
cos
);
transformVertex(
_vB.set(0.5, -0.5, 0),
_mvPosition,
center,
_worldScale,
sin,
cos
);
transformVertex(
_vC.set(0.5, 0.5, 0),
_mvPosition,
center,
_worldScale,
sin,
cos
);
_uvA.set(0, 0);
_uvB.set(1, 0);
_uvC.set(1, 1);
// check first triangle
let intersect = raycaster.ray.intersectTriangle(
_vA,
_vB,
_vC,
false,
_intersectPoint
);
if (intersect === null) {
// check second triangle
transformVertex(
_vB.set(-0.5, 0.5, 0),
_mvPosition,
center,
_worldScale,
sin,
cos
);
_uvB.set(0, 1);
intersect = raycaster.ray.intersectTriangle(
_vA,
_vC,
_vB,
false,
_intersectPoint
);
if (intersect === null) {
return;
}
}
const distance = raycaster.ray.origin.distanceTo(_intersectPoint);
if (distance < raycaster.near || distance > raycaster.far) return;
intersects.push({
distance: distance,
point: _intersectPoint.clone(),
uv: Triangle.getInterpolation(
_intersectPoint,
_vA,
_vB,
_vC,
_uvA,
_uvB,
_uvC,
new Vector2()
),
face: null,
object: this,
});
}
copy(source, recursive) {
super.copy(source, recursive);
if (source.center !== undefined) this.center.copy(source.center);
this.material = source.material;
return this;
}
}
function transformVertex(vertexPosition, mvPosition, center, scale, sin, cos) {
// compute position in camera space
_alignedPosition
.subVectors(vertexPosition, center)
.addScalar(0.5)
.multiply(scale);
// to check if rotation is not zero
if (sin !== undefined) {
_rotatedPosition.x =
cos * _alignedPosition.x - sin * _alignedPosition.y;
_rotatedPosition.y =
sin * _alignedPosition.x + cos * _alignedPosition.y;
} else {
_rotatedPosition.copy(_alignedPosition);
}
vertexPosition.copy(mvPosition);
vertexPosition.x += _rotatedPosition.x;
vertexPosition.y += _rotatedPosition.y;
// transform to world space
vertexPosition.applyMatrix4(_viewWorldMatrix);
}
export { Sprite };

6
test_files/test3.js Normal file
View file

@ -0,0 +1,6 @@
let something = Iterator.from([1,2,3]);
let someOtherThing = Iterator.from([4,5,6]);
let generate = function* () {
yield* something;
yield* someOtherThing;
}();

View file

@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
"rootDir": "src", "rootDir": "src",
"outDir": "dist", "outDir": "dist",
"strict": true, "strict": false,
"target": "es2017", "target": "es2017",
"module": "commonjs", "module": "commonjs",
"sourceMap": true, "sourceMap": true,
@ -10,6 +10,6 @@
"moduleResolution": "node", "moduleResolution": "node",
"types": ["bun-types"] "types": ["bun-types"]
}, },
"include": ["src"], "include": ["src", "index.ts"],
"exclude": ["babel"] "exclude": ["babel"]
} }