diff --git a/ets-tests/package.json b/ets-tests/package.json index 6bd77f1ed08249c05a2feb539088c59c158cbb38..fe6507fb55a64c5817bd6828b2a3e69ff2504276 100644 --- a/ets-tests/package.json +++ b/ets-tests/package.json @@ -12,7 +12,7 @@ "clean:all": "npm run clean && npm run clean:all --prefix ../arkoala-arkts", "copy:deps:m3": "npm run copy:arkoala:m3 -C ../arkoala-arkts && mkdir -p ../arkoala-arkts/build/bootPandaFiles && cp ../incremental/harness/build/harness.abc ../arkoala-arkts/build/bootPandaFiles/", "build:deps:m3": "npm run compile:native:node-host -C ../arkoala-arkts && npm run build:arkoala:m3 -C ../arkoala-arkts && npm run build:harness:inc:ui2abc -C ../incremental/harness && npm run build:loader:node -C ../arkoala-arkts && npm run copy:deps:m3", - "compile:m3": "node ../ui2abc/fast-arktsc --config ./ui2abcconfig-m3.json --compiler ../incremental/tools/panda/arkts/ui2abc --link-name ./build/tests-m3.abc && ninja ${NINJA_OPTIONS} -f build/ets-m3/abc/build.ninja", + "compile:m3": "node ../ui2abc/fast-arktsc --group-by 10 --config ./ui2abcconfig-m3.json --compiler ../incremental/tools/panda/arkts/ui2abc --link-name ./build/tests-m3.abc && ninja ${NINJA_OPTIONS} -f build/ets-m3/abc/build.ninja", "run:m3": "npm run compile:m3 && mkdir -p ../arkoala-arkts/build/userPandaFiles && cp ./build/tests-m3.abc ../arkoala-arkts/build/userPandaFiles/ && cd ../arkoala-arkts && ACE_LIBRARY_PATH=build PANDA_HOME=../incremental/tools/panda/node_modules/@panda/sdk node build/index.js panda:tests=StateIncrement", "all:m3": "npm run build:deps:m3 && npm run run:m3", "check": "npm run compile --prefix ../ui2abc/ui-plugins && npm run run:m3" diff --git a/incremental/tools/panda/arkts/ui2abc b/incremental/tools/panda/arkts/ui2abc index e9c4652a40e9a132215e64f73331cea104174193..eecf623552142b145eeaa3c239eb52facfca1802 100755 --- a/incremental/tools/panda/arkts/ui2abc +++ b/incremental/tools/panda/arkts/ui2abc @@ -14,5 +14,5 @@ # limitations under the License. SCRIPT_DIR=`dirname "${BASH_SOURCE[0]}"` -PANDA_SDK_PATH=${PANDA_SDK_PATH:=$SCRIPT_DIR/../node_modules/@panda/sdk} node $SCRIPT_DIR/../../../../ui2abc/libarkts/lib/es2panda.js "$@" +PANDA_SDK_PATH=${PANDA_SDK_PATH:=$SCRIPT_DIR/../node_modules/@panda/sdk} ${DEBUGGER} node -- $SCRIPT_DIR/../../../../ui2abc/libarkts/lib/es2panda.js "$@" diff --git a/ui2abc/libarkts/native/src/bridges.cc b/ui2abc/libarkts/native/src/bridges.cc index 3789af4cd1a280035b3b95c27e1e6d1fb1e3455d..20a4af43b335af2834a50c4f8b1c134fa37590e9 100644 --- a/ui2abc/libarkts/native/src/bridges.cc +++ b/ui2abc/libarkts/native/src/bridges.cc @@ -224,6 +224,16 @@ static KNativePointer impl_ProgramExternalSources(KNativePointer contextPtr, KNa } KOALA_INTEROP_2(ProgramExternalSources, KNativePointer, KNativePointer, KNativePointer); +static KNativePointer impl_ProgramDirectExternalSources(KNativePointer contextPtr, KNativePointer instancePtr) +{ + auto context = reinterpret_cast(contextPtr); + auto&& instance = reinterpret_cast(instancePtr); + std::size_t source_len = 0; + auto external_sources = GetImpl()->ProgramDirectExternalSources(context, instance, &source_len); + return StageArena::cloneVector(external_sources, source_len); +} +KOALA_INTEROP_2(ProgramDirectExternalSources, KNativePointer, KNativePointer, KNativePointer); + static KNativePointer impl_ProgramSourceFilePath(KNativePointer contextPtr, KNativePointer instancePtr) { auto context = reinterpret_cast(contextPtr); @@ -349,3 +359,28 @@ KNativePointer impl_OptionsArkTsConfig(KNativePointer context, KNativePointer op return (void*)result; } KOALA_INTEROP_2(OptionsArkTsConfig, KNativePointer, KNativePointer, KNativePointer) + + +KNativePointer impl_CreateCacheContextFromFile(KNativePointer configPtr, KStringPtr& source_file_namePtr, KNativePointer globalContextPtr, KBoolean isExternal) { + auto config = reinterpret_cast(configPtr); + auto globalContext = reinterpret_cast(globalContextPtr); + return GetImpl()->CreateCacheContextFromFile(config, getStringCopy(source_file_namePtr), globalContext, isExternal); +} +KOALA_INTEROP_4(CreateCacheContextFromFile, KNativePointer, KNativePointer, KStringPtr, KNativePointer, KBoolean) + +KNativePointer impl_CreateGlobalContext(KNativePointer configPtr, KStringArray externalFileListPtr, KUInt fileNum, KBoolean LspUsage) { + auto config = reinterpret_cast(configPtr); + const int headerLen = 4; + const char** files = StageArena::allocArray(fileNum); + uint8_t* filesPtr = (uint8_t*)externalFileListPtr; + std::size_t position = headerLen; + std::size_t strLen; + for (std::size_t i = 0; i < static_cast(fileNum); ++i) { + strLen = unpackUInt(filesPtr + position); + position += headerLen; + files[i] = StageArena::strdup(std::string(reinterpret_cast(filesPtr + position), strLen).c_str()); + position += strLen; + } + return GetImpl()->CreateGlobalContext(config, files, fileNum, LspUsage); +} +KOALA_INTEROP_4(CreateGlobalContext, KNativePointer, KNativePointer, KStringArray, KUInt, KBoolean) \ No newline at end of file diff --git a/ui2abc/libarkts/native/src/common.cc b/ui2abc/libarkts/native/src/common.cc index 6b9412c3fc6f345b797e6b018c290421ee56b198..6b45a9a01657fa578c8df40ad4ab418e9b3aa432 100644 --- a/ui2abc/libarkts/native/src/common.cc +++ b/ui2abc/libarkts/native/src/common.cc @@ -138,24 +138,6 @@ char* getStringCopy(KStringPtr& ptr) return StageArena::strdup(ptr.c_str() ? ptr.c_str() : ""); } -inline KUInt unpackUInt(const KByte* bytes) -{ - const KUInt BYTE_0 = 0; - const KUInt BYTE_1 = 1; - const KUInt BYTE_2 = 2; - const KUInt BYTE_3 = 3; - - const KUInt BYTE_1_SHIFT = 8; - const KUInt BYTE_2_SHIFT = 16; - const KUInt BYTE_3_SHIFT = 24; - return ( - bytes[BYTE_0] - | (bytes[BYTE_1] << BYTE_1_SHIFT) - | (bytes[BYTE_2] << BYTE_2_SHIFT) - | (bytes[BYTE_3] << BYTE_3_SHIFT) - ); -} - KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) { const std::size_t headerLen = 4; diff --git a/ui2abc/libarkts/native/src/common.h b/ui2abc/libarkts/native/src/common.h index 4d22eb8c078ee843f3d1d9aae283a2ba4dc00b0d..7b57d89a16f1dd760456a233f6ef923e29e37b00 100644 --- a/ui2abc/libarkts/native/src/common.h +++ b/ui2abc/libarkts/native/src/common.h @@ -55,7 +55,23 @@ string getString(KStringPtr ptr); char* getStringCopy(KStringPtr& ptr); -inline KUInt unpackUInt(const KByte* bytes); +inline KUInt unpackUInt(const KByte* bytes) +{ + const KUInt BYTE_0 = 0; + const KUInt BYTE_1 = 1; + const KUInt BYTE_2 = 2; + const KUInt BYTE_3 = 3; + + const KUInt BYTE_1_SHIFT = 8; + const KUInt BYTE_2_SHIFT = 16; + const KUInt BYTE_3_SHIFT = 24; + return ( + bytes[BYTE_0] + | (bytes[BYTE_1] << BYTE_1_SHIFT) + | (bytes[BYTE_2] << BYTE_2_SHIFT) + | (bytes[BYTE_3] << BYTE_3_SHIFT) + ); +} es2panda_ContextState intToState(KInt state); diff --git a/ui2abc/libarkts/src-host/es2panda.ts b/ui2abc/libarkts/src-host/es2panda.ts index bb1de0b9f024ac487458e0f4618e58e168b13737..30621d6a5e8bb11a01a02fc07ac1e4339763c4cc 100644 --- a/ui2abc/libarkts/src-host/es2panda.ts +++ b/ui2abc/libarkts/src-host/es2panda.ts @@ -15,12 +15,13 @@ import * as fs from "node:fs" import * as path from "node:path" -import { checkSDK, arktsGlobal as global, metaDatabase, runTransformer, CompilationOptions } from "@koalaui/libarkts" +import { checkSDK, arktsGlobal as global, metaDatabase, runTransformer, CompilationOptions, passStringArray } from "@koalaui/libarkts" import { CheckedBackFilter, PluginContextImpl } from "@koalaui/libarkts" import { Command } from "commander" import { filterSource, isNumber, throwError, withWarning } from "@koalaui/libarkts" import { Es2pandaContextState } from "@koalaui/libarkts" import { ArkTsConfig, Options, AstNode, Config, Context, createETSModuleFromContext, proceedToState, ProgramTransformer, rebindSubtree, recheckSubtree, dumpProgramInfo, dumpArkTsConfigInfo } from "@koalaui/libarkts" +import { nullptr, pointer } from "@koalaui/interop" function parseCommandLineArgs() { const commander = new Command() @@ -61,19 +62,19 @@ function parseCommandLineArgs() { } function insertPlugin( - source: string, transform: ProgramTransformer, state: Es2pandaContextState, pluginName: string, - dumpAst: boolean, + dumpAst: boolean, restart: boolean, + pluginContext: PluginContextImpl, updateWith?: (node: AstNode) => void ): AstNode { proceedToState(state) const script = createETSModuleFromContext() // Or this: const script = createETSModuleFromSource(source) if (script === undefined) { - throw new Error(`Failed to receive AST from es2panda for ${source}`) + throw new Error(`Failed to receive AST from es2panda`) } if (dumpAst) { @@ -81,12 +82,10 @@ function insertPlugin( console.log(filterSource(script.dumpSrc())) } - const context = new PluginContextImpl() - global.profiler.curPlugin = pluginName global.profiler.transformStarted() - runTransformer(global.compilerContext.program, state, restart, transform, context, { + runTransformer(global.compilerContext.program, state, restart, transform, pluginContext, { onProgramTransformStart(options: CompilationOptions) { if (!options.isMainProgram) global.profiler.transformDepStarted() }, @@ -94,7 +93,7 @@ function insertPlugin( if (!options.isMainProgram) global.profiler.transformDepEnded(state, pluginName) } }) - + global.profiler.transformEnded(state, pluginName) global.profiler.curPlugin = "" @@ -113,12 +112,12 @@ function insertPlugin( return script } -function restartCompiler(source: string, configPath: string, filePath: string, stdlib: string, outputPath: string, verbose: boolean = true) { +function restartCompiler(configPath: string, filePath: string, stdlib: string, outputPath: string, verbose: boolean = true) { if (verbose) { console.log(`restarting with config ${configPath}, file ${filePath}`) } const module = createETSModuleFromContext() - if (module == undefined) throw new Error(`Cannot restart compiler for ${source}`) + if (module == undefined) throw new Error(`Cannot restart compiler`) const filterTransform = new CheckedBackFilter() const srcText = filterSource( filterTransform.visitor(module) @@ -144,7 +143,17 @@ function restartCompiler(source: string, configPath: string, filePath: string, s } const defaultPandaSdk = "../../../incremental/tools/panda/node_modules/@panda/sdk" + +function findStdlib(): string { + const sdk = process.env.PANDA_SDK_PATH ?? withWarning( + defaultPandaSdk, + `PANDA_SDK_PATH not set, assuming ${defaultPandaSdk}` + ) + return `${sdk}/ets/stdlib` +} + function invokeWithPlugins( + globalContext: pointer, configPath: string, baseUrl: string, outDir: string, @@ -155,14 +164,9 @@ function invokeWithPlugins( restart: boolean, stage: number, pluginNames: string[], + pluginContext: PluginContextImpl ): void { - const source = fs.readFileSync(filePath).toString() - const sdk = process.env.PANDA_SDK_PATH ?? withWarning( - defaultPandaSdk, - `PANDA_SDK_PATH not set, assuming ${defaultPandaSdk}` - ) - const stdlib = `${sdk}/ets/stdlib` - + const stdlib = findStdlib() global.filePath = filePath global.outDir = outDir global.outputPath = outputPath @@ -175,14 +179,14 @@ function invokeWithPlugins( '--extension', 'ets', '--stdlib', - stdlib, + findStdlib(), '--output', outputPath ]).peer if (!global.configIsInitialized()) throw new Error(`Wrong config: path=${configPath} file=${filePath} stdlib=${stdlib} output=${outputPath}`) fs.mkdirSync(path.dirname(outputPath), {recursive: true}) - global.compilerContext = Context.createFromString(source) + global.compilerContext = Context.createFromFile(filePath, configPath)! // console.log("PLUGINS: ", pluginsByState.size, pluginsByState) @@ -213,7 +217,7 @@ function invokeWithPlugins( } pluginsApplied++ const before = Date.now() - restartCompiler(source, newConfigPath, newFilePath, stdlib, outputPath) + restartCompiler(newConfigPath, newFilePath, stdlib, outputPath) const after = Date.now() configPath = newConfigPath filePath = newFilePath @@ -226,17 +230,17 @@ function invokeWithPlugins( global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_PARSED pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_PARSED)?.forEach(plugin => { if (!terminate) - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_PARSED, pluginNames[pluginsApplied], dumpAst, restart) + insertPlugin(plugin, Es2pandaContextState.ES2PANDA_STATE_PARSED, pluginNames[pluginsApplied], dumpAst, restart, pluginContext) restartProcedure() }) - + if (terminate) return global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_BOUND pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_BOUND)?.forEach(plugin => { if (!terminate) - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_BOUND, pluginNames[pluginsApplied], dumpAst, restart, rebindSubtree) + insertPlugin(plugin, Es2pandaContextState.ES2PANDA_STATE_BOUND, pluginNames[pluginsApplied], dumpAst, restart, pluginContext, rebindSubtree) restartProcedure() }) @@ -246,7 +250,7 @@ function invokeWithPlugins( global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_CHECKED pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_CHECKED)?.forEach(plugin => { if (!terminate) - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_CHECKED, pluginNames[pluginsApplied], dumpAst, restart, recheckSubtree) + insertPlugin(plugin, Es2pandaContextState.ES2PANDA_STATE_CHECKED, pluginNames[pluginsApplied], dumpAst, restart, pluginContext, recheckSubtree) restartProcedure() }) @@ -263,6 +267,9 @@ function invokeWithPlugins( dumpProgramInfo(global.compilerContext.program) proceedToState(Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED) + + global.es2panda._DestroyContext(global.context) + global.es2panda._DestroyConfig(global.config) } const exportsFromInitialFile: string[] = [] @@ -333,16 +340,33 @@ export function main() { const outDir = path.resolve(path.dirname(configPath), compilerOptions.outDir ?? ".") const plugins = compilerOptions.plugins ?? [] const pluginNames = plugins.map((it: any) => `${it.name}-${it.stage}`) - + const pluginContext = new PluginContextImpl() const pluginsByState = readAndSortPlugins(configDir, plugins) + const globalConfig = Config.create([ + '_', + '--arktsconfig', + configPath, + files[0], + '--extension', + 'ets', + '--stdlib', + findStdlib(), + '--output', + outputs[0] + ]) + const globalContext = global.es2panda._CreateGlobalContext( + globalConfig.peer, passStringArray(files), files.length, false + ) + console.log(`GLOBAL2 IS ${globalContext.toString(16)}`) for (var i = 0; i < files.length; i++) { global.profiler.compilationStarted(files[i]) - invokeWithPlugins(configPath, baseUrl, outDir, files[i], outputs[i], pluginsByState, dumpAst, restartStages, stage, pluginNames) + invokeWithPlugins(globalContext, configPath, baseUrl, outDir, files[i], outputs[i], pluginsByState, dumpAst, restartStages, stage, pluginNames, pluginContext) global.profiler.compilationEnded() global.profiler.report() global.profiler.reportToFile(true) } + } function reportErrorAndExit(message: string): never { diff --git a/ui2abc/libarkts/src/Es2pandaNativeModule.ts b/ui2abc/libarkts/src/Es2pandaNativeModule.ts index 192eacb42e101ee3584e517408b3fc536a8a5432..3fbe4566fab939831c18f1de35ac144b702c9936 100644 --- a/ui2abc/libarkts/src/Es2pandaNativeModule.ts +++ b/ui2abc/libarkts/src/Es2pandaNativeModule.ts @@ -17,6 +17,8 @@ import { KNativePointer as KPtr, KInt, KBoolean, + KStringPtr, + KStringArrayPtr, KNativePointer, registerNativeModuleLibraryName, loadNativeModuleLibrary, @@ -40,6 +42,9 @@ export class Es2pandaNativeModule { _AstNodeRecheck(context: KPtr, node: KPtr): void { throw new Error("Not implemented") } + _AstNodeDeepClone(context: KPtr, node: KPtr): KPtr { + throw new Error("Not implemented") + } _ContextState(context: KPtr): KInt { throw new Error("Not implemented") } @@ -61,6 +66,9 @@ export class Es2pandaNativeModule { _CreateContextFromString(config: KPtr, source: String, filename: String): KPtr { throw new Error("Not implemented") } + _CreateContextFromFile(config: KPtr, filename: String): KPtr { + throw new Error("Not implemented") + } _DestroyContext(context: KPtr): void { throw new Error("Not implemented") } @@ -103,6 +111,9 @@ export class Es2pandaNativeModule { _ProgramExternalSources(context: KNativePointer, instance: KNativePointer): KNativePointer { throw new Error("Not implemented"); } + _ProgramDirectExternalSources(context: KNativePointer, instance: KNativePointer): KNativePointer { + throw new Error("Not implemented"); + } _ExternalSourceName(instance: KNativePointer): KNativePointer { throw new Error("Not implemented"); } @@ -136,6 +147,12 @@ export class Es2pandaNativeModule { _OptionsArkTsConfig(context: KNativePointer, options: KNativePointer): KNativePointer { throw new Error("Not implemented"); } + _CreateCacheContextFromFile(config: KNativePointer, source_file_name: KStringPtr, globalContext: KNativePointer, isExternal: KBoolean): KNativePointer { + throw new Error("Not implemented"); + } + _CreateGlobalContext(config: KNativePointer, externalFileList: KStringArrayPtr, fileNum: KUInt, lspUsage: KBoolean): KNativePointer { + throw new Error("Not implemented"); + } } export function findNativeModule(): string { diff --git a/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts b/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts index 2d0a48cc5df9651e9cf2b285643e3ce569e56189..eb9f7b5f4269b598ea616821c448337360cea0a0 100644 --- a/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts +++ b/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts @@ -16,6 +16,7 @@ import { KNativePointer } from "@koalaui/interop" import { defaultFilter, listPrograms } from "./plugins" import { Program } from "../generated" +import { programGetExternalSources } from "./node-utilities/Program" export class ProgramProvider { // TODO: migrate to wrappers instead of pointers @@ -27,6 +28,31 @@ export class ProgramProvider { this.queue = [mainProgram] } + static dumpDeps(program: Program): string { + let seen = new Set() + let queue: Program[] = [] + let result = `digraph "Dependencies of ${program.absoluteName}" {` + queue.push(program) + while (queue.length > 0) { + const current = queue.shift()! + const listed = programGetExternalSources(current) + listed.forEach(source => { + if (!defaultFilter(source.getName())) return + source.programs.forEach(program => { + if (program.peer != current.peer) { + result += `"${current.fileName}" -> "${program.fileName}";\n` + if (!seen.has(program.peer)) { + seen.add(program.peer) + queue.push(program) + } + } + }) + }) + } + result += "}" + return result + } + updateQueue() { const listed = listPrograms(this.mainProgram, this.filter) for (const program of listed) { diff --git a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts index 55fbcf5a0bf6046a026cdc1f29e35ff879572011..c00f242496fe50474d0ed315849deda78b53d942 100644 --- a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts +++ b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts @@ -95,8 +95,13 @@ export abstract class AstNode extends ArktsObject { return unpackString(global.es2panda._AstNodeDumpModifiers(global.context, this.peer)) } - public clone(): this { - return unpackNonNullableNode(global.generatedEs2panda._AstNodeClone(global.context, this.peer, this.parent.peer)); + public clone(parent: KNativePointer = nullptr): this { + return unpackNonNullableNode(global.generatedEs2panda._AstNodeClone( + global.context, this.peer, parent)) + } + + public deepClone(): this { + return unpackNonNullableNode(global.es2panda._AstNodeDeepClone(global.context, this.peer)) } public get parent(): AstNode { diff --git a/ui2abc/libarkts/src/arkts-api/peers/Config.ts b/ui2abc/libarkts/src/arkts-api/peers/Config.ts index ca7984740d88ddc1fbf29dc412c51b59db758852..1bac26cbdaec01252d5afdc480b3876bdfc8dba9 100644 --- a/ui2abc/libarkts/src/arkts-api/peers/Config.ts +++ b/ui2abc/libarkts/src/arkts-api/peers/Config.ts @@ -17,6 +17,7 @@ import { ArktsObject } from "./ArktsObject" import { global } from "../static/global" import { passStringArray } from "../utilities/private" import { KNativePointer } from "@koalaui/interop" +import * as fs from "fs" export class Config extends ArktsObject { constructor(peer: KNativePointer) { @@ -33,6 +34,14 @@ export class Config extends ArktsObject { ) } + static createFromFile( + path: string + ): Config { + return new Config( + global.es2panda._CreateConfig(4, passStringArray(["", "--arktsconfig", path, "XXX.ets"])) + ) + } + static createDefault(): Config { if (global.configIsInitialized()) { console.warn(`Config already initialized`) diff --git a/ui2abc/libarkts/src/arkts-api/peers/Context.ts b/ui2abc/libarkts/src/arkts-api/peers/Context.ts index 8535e95fef9482ccd513b9db1ef12508dea87748..a5342cfaa2ae78d2cc2ca4723d7b24ed50023a79 100644 --- a/ui2abc/libarkts/src/arkts-api/peers/Context.ts +++ b/ui2abc/libarkts/src/arkts-api/peers/Context.ts @@ -42,23 +42,27 @@ export class Context extends ArktsObject { } static createFromFile(filePath: string, configPath: string): Context | undefined { - const config = Config.create([ - "", - "--arktsconfig", - configPath, - '--extension', - 'ets', - filePath - ]) + const config = Config.createFromFile(configPath) return new Context( - global.es2panda._CreateContextFromString( + global.es2panda._CreateContextFromFile( config.peer, - passString(fs.readFileSync(filePath, 'utf-8')), passString(filePath) ) ) } + static createCacheFromFile(filePath: string, configPath: string, globalContext: KNativePointer, isExternal: boolean): Context | undefined { + const config = Config.createFromFile(configPath) + return new Context( + global.es2panda._CreateCacheContextFromFile( + config.peer, + passString(filePath), + globalContext, + isExternal + ) + ) + } + get program(): Program { return new Program(global.es2panda._ContextProgram(this.peer)); } diff --git a/ui2abc/libarkts/src/plugin-utils.ts b/ui2abc/libarkts/src/plugin-utils.ts index f451321f962764d1582283a952855f2786196173..6b31c1c28efbcfccf2ee1eb5418962a091b017d8 100644 --- a/ui2abc/libarkts/src/plugin-utils.ts +++ b/ui2abc/libarkts/src/plugin-utils.ts @@ -24,15 +24,43 @@ import { Program, inferVoidReturnType, ProgramProvider, - CompilationOptions + CompilationOptions, + AbstractVisitor } from "./arkts-api" -import { AstNode } from "./reexport-for-generated" +import { AstNode, KNativePointer } from "./reexport-for-generated" +import { factory } from "./arkts-api/factory/nodeFactory" export interface RunTransformerHooks { onProgramTransformStart?(options: CompilationOptions): void onProgramTransformEnd?(options: CompilationOptions): void } +class CloneVisitor extends AbstractVisitor { + visitor(node: AstNode, options?: object): AstNode { + return this.visitEachChild(node) + } +} + +function deepClone(ast: AstNode): AstNode { + if (true) + return ast.clone() + else + return new CloneVisitor().visitor(ast) +} + +class ASTCache { + processedPrograms = new Set() + constructor() {} + find(program: Program): boolean { + return this.processedPrograms.has(program.absoluteName) + } + update(program: Program) { + this.processedPrograms.add(program.absoluteName) + } +} + +let verbose = false + export function runTransformer(prog: Program, state: Es2pandaContextState, restart: boolean, transform: ProgramTransformer, pluginContext: PluginContext, hooks: RunTransformerHooks = {}) { // Program provider used to provide programs to transformer dynamically relative to inserted imports const provider = new ProgramProvider(prog) @@ -41,6 +69,12 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, resta let currentProgram = provider.next() let isMainProgram = true + let cache = pluginContext.parameter("ASTCache") + if (!cache) { + cache = new ASTCache() + pluginContext.setParameter("ASTCache", cache) + } + while (currentProgram) { // Options passed to plugin and hooks const options: CompilationOptions = { @@ -54,7 +88,7 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, resta // AST to be transformed const ast = currentProgram.ast - + // Save currently existing imports in the program const importStorage = new ImportStorage(currentProgram, state == Es2pandaContextState.ES2PANDA_STATE_PARSED) @@ -62,7 +96,13 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, resta stageSpecificPreFilters(ast, state) // Run the plugin itself - transform?.(currentProgram, options, pluginContext) + if (!cache.find(currentProgram)) { + //console.log(`APPLY TRANSFORMATION FOR ${currentProgram.absoluteName}`) + transform?.(currentProgram, options, pluginContext) + cache.update(currentProgram) + } else { + //console.log(`SKIP TRANSFORMATION FOR ${currentProgram.absoluteName}`) + } // Run some common plugins that should be run after plugin usage and depends on the current stage stageSpecificPostFilters(ast, state) diff --git a/ui2abc/ui-plugins/src/checked-stage-plugin.ts b/ui2abc/ui-plugins/src/checked-stage-plugin.ts index 9e80c4e0b8597d0e4a6725f71e3a1763fd3eb7dd..1d3f0b45ff457045ca513da97db3cb69e234bace 100644 --- a/ui2abc/ui-plugins/src/checked-stage-plugin.ts +++ b/ui2abc/ui-plugins/src/checked-stage-plugin.ts @@ -28,9 +28,7 @@ export default function checkedTransformer( userPluginOptions?: TransformerOptions ): arkts.ProgramTransformer { return (program: arkts.Program, _compilationOptions: arkts.CompilationOptions, context: arkts.PluginContext) => { - const structsResolver = context.parameter("structsTable")! - const importer = context.parameter("importer")!; - + const structsResolver = context.parameter("structsTable")!; [ new InstantiateFactoryHelper(), new EtsFirstArgTransformer(),