From 9c345557a673e4af777983ce91a13c82629032bf Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 14 Feb 2025 16:40:24 +0300 Subject: [PATCH 1/3] Created the annotate tool for @memo annotations Signed-off-by: Alexander Gorshenev --- incremental/tools/annotate/package.json | 24 ++++++++++++++++ incremental/tools/annotate/src/annotate.ts | 32 ++++++++++++++++++++++ incremental/tools/annotate/test/test.ts | 1 + incremental/tools/annotate/tsconfig.json | 15 ++++++++++ 4 files changed, 72 insertions(+) create mode 100644 incremental/tools/annotate/package.json create mode 100644 incremental/tools/annotate/src/annotate.ts create mode 100644 incremental/tools/annotate/test/test.ts create mode 100644 incremental/tools/annotate/tsconfig.json diff --git a/incremental/tools/annotate/package.json b/incremental/tools/annotate/package.json new file mode 100644 index 000000000..a078de275 --- /dev/null +++ b/incremental/tools/annotate/package.json @@ -0,0 +1,24 @@ +{ + "name": "@koalaui/annotate", + "version": "1.5.0+devel", + "description": "", + "main": "lib/annotate.js", + "bin": "lib/annotate.js", + "scripts": { + "clean": "rimraf out lib", + "compile": "npx tsc -p ." + }, + "keywords": [], + "dependencies": { + "commander": "^10.0.0", + "minimatch": "10.0.1" + }, + "devDependencies": { + "@types/node": "^18.0.0", + "typescript": "^4.9.5", + "webpack": "5.95.0", + "copy-webpack-plugin": "12.0.2", + "webpack-cli": "5.1.4", + "rimraf": "^6.0.1" + } +} diff --git a/incremental/tools/annotate/src/annotate.ts b/incremental/tools/annotate/src/annotate.ts new file mode 100644 index 000000000..8b69430ce --- /dev/null +++ b/incremental/tools/annotate/src/annotate.ts @@ -0,0 +1,32 @@ +import * as fs from 'fs' +import * as path from 'path' + +const inputDir = process.argv[2] +const outputDir = process.argv[3] +const memoImport = process.argv[4] ?? "@koalaui/runtime" + +console.log("input = ", inputDir) +console.log("output = ", outputDir) + +const files = fs.readdirSync(inputDir, { recursive: true, withFileTypes: true }) + .filter(it => it.isFile()) + .map(it => `${it.parentPath}/${it.name}`) + .map(it =>path.relative(inputDir, it)) + +fs.mkdirSync(outputDir, {recursive: true}) + +files.forEach(it => { + const inputFile = path.join(inputDir, it) + const outputFile = path.join(outputDir, it) + const text = fs.readFileSync(inputFile, 'utf8').toString() + const newText = convertMemo(text) + console.log(inputFile, " -> ", outputFile) + fs.mkdirSync(path.dirname(outputFile), {recursive: true}) + fs.writeFileSync(outputFile, newText, 'utf8') +}) + +function convertMemo(text: string): string { + return `import { memo } from "${memoImport}"\n` + text.replaceAll(/\/\*\* @memo \*\//g, "@memo") +} + + diff --git a/incremental/tools/annotate/test/test.ts b/incremental/tools/annotate/test/test.ts new file mode 100644 index 000000000..5c5b82759 --- /dev/null +++ b/incremental/tools/annotate/test/test.ts @@ -0,0 +1 @@ +/** @memo */ diff --git a/incremental/tools/annotate/tsconfig.json b/incremental/tools/annotate/tsconfig.json new file mode 100644 index 000000000..3de03062e --- /dev/null +++ b/incremental/tools/annotate/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["esnext"], + "module": "CommonJS", + "moduleResolution": "node", + "sourceMap": true, + "noEmitOnError": true, + "strict": true, + "removeComments": false, + "outDir": "lib", + "rootDir": "src" + }, + "include": ["./src"] +} -- Gitee From d1330dabbf4df14ebd7ae1dd90d34db41fb3e7b3 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 14 Feb 2025 17:19:27 +0300 Subject: [PATCH 2/3] more Signed-off-by: Alexander Gorshenev --- incremental/runtime/package.json | 3 ++- incremental/tools/annotate/src/annotate.ts | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/incremental/runtime/package.json b/incremental/runtime/package.json index 16e37cdcd..802eddd28 100644 --- a/incremental/runtime/package.json +++ b/incremental/runtime/package.json @@ -18,6 +18,7 @@ "panda:sdk:install": "cd ../tools/panda && npm run panda:sdk:install", "arkts:test:run": "bash ../tools/panda/arkts/ark build/runtime-tests.abc --ark-boot-files ../compat/build/compat.abc:../common/build/common.abc:../harness/build/harness.abc --ark-entry-point @koalaui.runtime-tests.test-arkts.tests.ETSGLOBAL::main", "arkts:test": "npm run panda:sdk:install && npm run build:compat && npm run build:common && npm run build:harness && npm run build:runtime:with:tests && npm run arkts:test:run", + "annotate": "node ../tools/annotate ./src build/annotate/src '../annotate'", "unmemoize": "mkdir -p build/unmemoized/abc && mkdir -p build/test/lib && ets-tsc -b tsconfig-unmemoize.json && mkdir -p build/test/lib", "unmemoize:with:tests": "npm run compile:all --prefix ../harness && mkdir -p build/unmemoized/abc && mkdir -p build/test/lib && ets-tsc -b tsconfig-unmemoize-with-tests.json && mkdir -p build/test/lib", "compile:arkts": "npm run unmemoize && ../tools/panda/arkts/arktsc --arktsconfig arktsconfig-run-unmemoized.json", @@ -55,4 +56,4 @@ "mocha": "^9.2.2", "source-map-support": "^0.5.21" } -} \ No newline at end of file +} diff --git a/incremental/tools/annotate/src/annotate.ts b/incremental/tools/annotate/src/annotate.ts index 8b69430ce..ca2351f7f 100644 --- a/incremental/tools/annotate/src/annotate.ts +++ b/incremental/tools/annotate/src/annotate.ts @@ -26,7 +26,13 @@ files.forEach(it => { }) function convertMemo(text: string): string { - return `import { memo } from "${memoImport}"\n` + text.replaceAll(/\/\*\* @memo \*\//g, "@memo") + return `import { memo } from "${memoImport}"\n` + + text + .replaceAll(/\/\*\* @memo \*\//g, "@memo") + .replaceAll(/\/\*\* @memo:interinsic \*\//g, "@memo_intrinsic") + .replaceAll(/\/\*\* @memo:stable \*\//g, "@memo_stable") + .replaceAll(/\/\*\* @memo:entry \*\//g, "@memo_entry") + .replaceAll(/\/\*\* @skip:memo \*\//g, "@memo_skip") } -- Gitee From 8677ea1940a632ab0129cef6079b7d2567f291a0 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Sat, 15 Feb 2025 03:11:56 +0300 Subject: [PATCH 3/3] Convert jsdocs to @memo annotation with annotate tool Signed-off-by: Alexander Gorshenev --- incremental/demo-playground/package.json | 3 + incremental/runtime/package.json | 4 +- incremental/runtime/src/index.ts | 3 +- incremental/runtime/src/memo/remember.ts | 4 +- incremental/tools/annotate/src/annotate.ts | 85 ++++++++++++++-------- 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/incremental/demo-playground/package.json b/incremental/demo-playground/package.json index 2a01209b2..88d08a607 100644 --- a/incremental/demo-playground/package.json +++ b/incremental/demo-playground/package.json @@ -23,11 +23,14 @@ "compile:arkts:unmemoize": "ets-tsc -b tsconfig-unmemoize.json", "compile:arkts:unmemoized": "bash ../tools/panda/arkts/arktsc --arktsconfig arktsconfig-run-unmemoized.json build/unmemoized/src/main.ts --output build/unmemoized/src/main.abc", "compile:arkts:unmemoizing": "npm run compile:unmemoize && npm run compile:arkts:unmemoized", + "annotate": "node ../tools/annotate ./src build/annotated/src '@koalaui/runtime'", + "compile:arkts:annotated": "bash ../tools/panda/arkts/arktsc --arktsconfig arktsconfig-annotated.json build/annotated/src/main.ts --output build/annotated/src/main.abc", "panda:sdk:install": "cd ../tools/panda && npm run panda:sdk:install", "run": "npm run compile && node lib/js/app.js", "run:unmemoizing": "npm run compile:unmemoizing && node lib/unmemoized/js/app.js", "run:panda": "bash ../tools/panda/arkts/ark build/abc/src/main.abc --ark-boot-files $(find ../compat/build/abc ../common/build/abc/ ../runtime/build/abc/ -name '*.abc' | paste -sd ':' -) --ark-entry-point main.ETSGLOBAL::main", "run:panda:unmemoizing:linked": "bash ../tools/panda/arkts/ark build/unmemoized/src/main.abc --ark-boot-files ../runtime/build/incremental.abc --ark-entry-point @koalaui.demo.build.unmemoized.src.main.ETSGLOBAL::main", + "run:panda:annotated:linked": "bash ../tools/panda/arkts/ark build/annotated/src/main.abc --ark-boot-files ../runtime/build/annotated/incremental.abc --ark-entry-point @koalaui.demo.build.annotated.src.main.ETSGLOBAL::main", "run:panda:unmemoizing": "npm run compile:arkts:unmemoizing && npm run build:incremental:inc --prefix ../runtime && npm run run:panda:unmemoizing:linked", "clean:unmemoized": "rimraf unmemoized", "clean": "rimraf build unmemoized" diff --git a/incremental/runtime/package.json b/incremental/runtime/package.json index 802eddd28..32d92a5f1 100644 --- a/incremental/runtime/package.json +++ b/incremental/runtime/package.json @@ -18,10 +18,11 @@ "panda:sdk:install": "cd ../tools/panda && npm run panda:sdk:install", "arkts:test:run": "bash ../tools/panda/arkts/ark build/runtime-tests.abc --ark-boot-files ../compat/build/compat.abc:../common/build/common.abc:../harness/build/harness.abc --ark-entry-point @koalaui.runtime-tests.test-arkts.tests.ETSGLOBAL::main", "arkts:test": "npm run panda:sdk:install && npm run build:compat && npm run build:common && npm run build:harness && npm run build:runtime:with:tests && npm run arkts:test:run", - "annotate": "node ../tools/annotate ./src build/annotate/src '../annotate'", + "annotate": "node ../tools/annotate ./src build/annotated/src 'annotations'", "unmemoize": "mkdir -p build/unmemoized/abc && mkdir -p build/test/lib && ets-tsc -b tsconfig-unmemoize.json && mkdir -p build/test/lib", "unmemoize:with:tests": "npm run compile:all --prefix ../harness && mkdir -p build/unmemoized/abc && mkdir -p build/test/lib && ets-tsc -b tsconfig-unmemoize-with-tests.json && mkdir -p build/test/lib", "compile:arkts": "npm run unmemoize && ../tools/panda/arkts/arktsc --arktsconfig arktsconfig-run-unmemoized.json", + "compile:arkts:annotated": "npx fast-arktsc --input-files ./arktsconfig-annotated.json --output-dir ./build/annotated/ --compiler ../tools/panda/arkts/arktsc --link-name runtime && PANDA_SDK_PATH=../tools/panda/node_modules/@panda/sdk ninja ${NINJA_OPTIONS} -f build/annotated/build.ninja", "build:compat": "npm run build:compat --prefix ../compat", "build:compat:inc": "npm run build:compat:inc --prefix ../compat", "build:common": "npm run build:common --prefix ../common", @@ -35,6 +36,7 @@ "build:incremental:components": "npm run build:compat && npm run build:common && npm run build:runtime", "build:incremental:components:inc": "npm run build:compat:inc && npm run build:common:inc && npm run build:runtime:inc", "link:incremental": "../tools/panda/arkts/arklink --output build/incremental.abc -- ../compat/build/compat.abc ../common/build/common.abc build/runtime.abc", + "link:annotated:incremental": "../tools/panda/arkts/arklink --output build/annotated/incremental.abc -- ../compat/build/compat.abc ../common/build/common.abc build/annotated/runtime.abc", "build:incremental": "npm run build:incremental:components && npm run link:incremental", "build:incremental:inc": "npm run build:incremental:components:inc && npm run link:incremental", "clean:incremental": "npm run clean" diff --git a/incremental/runtime/src/index.ts b/incremental/runtime/src/index.ts index 6c584c0f6..40959ec5e 100644 --- a/incremental/runtime/src/index.ts +++ b/incremental/runtime/src/index.ts @@ -93,7 +93,7 @@ export { contextNode, } from "./memo/node" export { - memo, + memoize, memoLifecycle, once, remember, @@ -162,3 +162,4 @@ export { PrimeNumbers } from "./tree/PrimeNumbers" export { ReadonlyTreeNode } from "./tree/ReadonlyTreeNode" export { TreeNode } from "./tree/TreeNode" export { TreePath } from "./tree/TreePath" + diff --git a/incremental/runtime/src/memo/remember.ts b/incremental/runtime/src/memo/remember.ts index 97bf91867..827f6a6f7 100644 --- a/incremental/runtime/src/memo/remember.ts +++ b/incremental/runtime/src/memo/remember.ts @@ -30,7 +30,7 @@ import { ArrayState, ControlledScope, MutableState } from "../states/State" * @experimental */ /** @memo:intrinsic */ -export function memo(compute: () => Value): Value { +export function memoize(compute: () => Value): Value { const scope = __context().scope(__id()) return scope.unchanged ? scope.cached : scope.recache(compute()) } @@ -83,7 +83,7 @@ export function once(callback: () => void): void { * * @param compute - a function to compute cacheable result * @returns the last calculated value - * @see memo + * @see memoize */ /** @memo:intrinsic */ export function remember(compute: () => Value): Value { diff --git a/incremental/tools/annotate/src/annotate.ts b/incremental/tools/annotate/src/annotate.ts index ca2351f7f..df3a4cbad 100644 --- a/incremental/tools/annotate/src/annotate.ts +++ b/incremental/tools/annotate/src/annotate.ts @@ -1,38 +1,59 @@ import * as fs from 'fs' import * as path from 'path' +import { text } from 'stream/consumers' -const inputDir = process.argv[2] -const outputDir = process.argv[3] -const memoImport = process.argv[4] ?? "@koalaui/runtime" - -console.log("input = ", inputDir) -console.log("output = ", outputDir) - -const files = fs.readdirSync(inputDir, { recursive: true, withFileTypes: true }) - .filter(it => it.isFile()) - .map(it => `${it.parentPath}/${it.name}`) - .map(it =>path.relative(inputDir, it)) - -fs.mkdirSync(outputDir, {recursive: true}) - -files.forEach(it => { - const inputFile = path.join(inputDir, it) - const outputFile = path.join(outputDir, it) - const text = fs.readFileSync(inputFile, 'utf8').toString() - const newText = convertMemo(text) - console.log(inputFile, " -> ", outputFile) - fs.mkdirSync(path.dirname(outputFile), {recursive: true}) - fs.writeFileSync(outputFile, newText, 'utf8') -}) - -function convertMemo(text: string): string { - return `import { memo } from "${memoImport}"\n` + - text - .replaceAll(/\/\*\* @memo \*\//g, "@memo") - .replaceAll(/\/\*\* @memo:interinsic \*\//g, "@memo_intrinsic") - .replaceAll(/\/\*\* @memo:stable \*\//g, "@memo_stable") - .replaceAll(/\/\*\* @memo:entry \*\//g, "@memo_entry") - .replaceAll(/\/\*\* @skip:memo \*\//g, "@memo_skip") +export function main() { + + const inputDir = process.argv[2] + const outputDir = process.argv[3] + const memoImport = process.argv[4] ?? "@koalaui/runtime" + + console.log("input = ", inputDir) + console.log("output = ", outputDir) + + const readdirSyncRecursive: (dir: string) => string[] = (dir: string) => + fs.readdirSync(dir).reduce((files: string[], file: string) => { + const name = path.join(dir, file) + return fs.lstatSync(name).isDirectory() ? [...files, ...readdirSyncRecursive(name)] : [...files, name] + }, []) + + + const files = readdirSyncRecursive(inputDir) + .map(it => path.relative(inputDir, it)) + + fs.mkdirSync(outputDir, { recursive: true }) + + files.forEach(it => { + const inputFile = path.join(inputDir, it) + const outputFile = path.join(outputDir, it) + const text = fs.readFileSync(inputFile, 'utf8').toString() + const newText = convertMemo(text, memoImport) + console.log(inputFile, " -> ", outputFile) + fs.mkdirSync(path.dirname(outputFile), { recursive: true }) + fs.writeFileSync(outputFile, newText, 'utf8') + }) + + const annotations = ` +export @interface memo {} +export @interface memo_intrinsic {} +export @interface memo_entry {} +export @interface memo_stable {} +export @interface memo_skip {} +` + + fs.mkdirSync(path.join(outputDir, "annotations"), {recursive: true}) + fs.writeFileSync(path.join(outputDir, "annotations/index.ts"), annotations, 'utf8') +} + +function convertMemo(text: string, memoImport: string): string { + return `import { memo, memo_intrinsic, memo_entry, memo_stable, memo_skip } from "${memoImport}"\n` + + text + .replaceAll(/\/\*\* @memo \*\//g, "@memo") + .replaceAll(/\/\*\* @memo:interinsic \*\//g, "@memo_intrinsic") + .replaceAll(/\/\*\* @memo:stable \*\//g, "@memo_stable") + .replaceAll(/\/\*\* @memo:entry \*\//g, "@memo_entry") + .replaceAll(/\/\*\* @skip:memo \*\//g, "@memo_skip") } +main() -- Gitee