From 2237e146e795d1be2b717246a8737cce079f1531 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 5 Jun 2025 11:48:38 +0300 Subject: [PATCH 1/4] WIP Signed-off-by: Nikolay Igotti --- ui2abc/libarkts/src-host/es2panda.ts | 4 ++-- .../libarkts/src/arkts-api/ProgramProvider.ts | 23 +++++++++++++++++++ ui2abc/libarkts/src/plugin-utils.ts | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ui2abc/libarkts/src-host/es2panda.ts b/ui2abc/libarkts/src-host/es2panda.ts index 3e7b89fdef..a0471a814c 100644 --- a/ui2abc/libarkts/src-host/es2panda.ts +++ b/ui2abc/libarkts/src-host/es2panda.ts @@ -78,7 +78,7 @@ function insertPlugin( console.log(filterSource(script.dumpSrc())) } - + global.profiler.curPlugin = pluginName global.profiler.transformStarted() @@ -93,7 +93,7 @@ function insertPlugin( return !restart } }) - + global.profiler.transformEnded(state, pluginName) global.profiler.curPlugin = "" diff --git a/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts b/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts index f73298098d..3c8f96a1f2 100644 --- a/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts +++ b/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts @@ -15,6 +15,7 @@ import { KNativePointer } from "@koalaui/interop" import { defaultFilter, listPrograms, ProgramWithName } from "./plugins" +import { Program } from "../generated" export class ProgramProvider { // TODO: migrate to wrappers instead of pointers @@ -26,6 +27,28 @@ export class ProgramProvider { this.queue = [mainProgram] } + static dumpDeps(program: Program): string { + let seen = new Set() + let queue: Program[] = [] + let result = `digraph "Deps" {` + queue.push(program) + while (queue.length > 0) { + const current = queue.shift()! + const listed = listPrograms(current, defaultFilter) + listed.forEach(it => { + if (it.program.peer != current.peer) { + result += `"${current.fileName}" -> "${it.program.fileName}";\n` + if (!seen.has(it.program.peer)) { + seen.add(it.program.peer) + queue.push(it.program) + } + } + }) + } + result += "}" + return result + } + updateQueue() { const listed = listPrograms(this.mainProgram.program, this.filter) for (const program of listed) { diff --git a/ui2abc/libarkts/src/plugin-utils.ts b/ui2abc/libarkts/src/plugin-utils.ts index 1f33c3c4c4..91d8b54aab 100644 --- a/ui2abc/libarkts/src/plugin-utils.ts +++ b/ui2abc/libarkts/src/plugin-utils.ts @@ -50,6 +50,7 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, trans hooks.onProgramTransformStart?.(runCtx) const ast = currentProgram.program.ast as ETSModule + console.log(`PROCESS [P] ${currentProgram.program.absoluteName}`) const importStorage = new ImportStorage(currentProgram.program, state == Es2pandaContextState.ES2PANDA_STATE_PARSED) stageSpecificPreFilters(ast, state) -- Gitee From 912b793c9f5c74f2a3b11472d48d9aa7c90c61c5 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 5 Jun 2025 14:15:55 +0300 Subject: [PATCH 2/4] Cache attempt Signed-off-by: Nikolay Igotti --- ui2abc/libarkts/native/src/bridges.cc | 10 ++++ ui2abc/libarkts/src/Es2pandaNativeModule.ts | 3 ++ .../libarkts/src/arkts-api/ProgramProvider.ts | 22 ++++---- .../src/arkts-api/node-utilities/Program.ts | 7 +++ ui2abc/libarkts/src/plugin-utils.ts | 53 +++++++++++++++++-- ui2abc/ui-plugins/src/checked-stage-plugin.ts | 4 +- 6 files changed, 83 insertions(+), 16 deletions(-) diff --git a/ui2abc/libarkts/native/src/bridges.cc b/ui2abc/libarkts/native/src/bridges.cc index 382bb5b2f7..2bf7e80830 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); diff --git a/ui2abc/libarkts/src/Es2pandaNativeModule.ts b/ui2abc/libarkts/src/Es2pandaNativeModule.ts index d96eaff104..35d3fd5c69 100644 --- a/ui2abc/libarkts/src/Es2pandaNativeModule.ts +++ b/ui2abc/libarkts/src/Es2pandaNativeModule.ts @@ -103,6 +103,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"); } diff --git a/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts b/ui2abc/libarkts/src/arkts-api/ProgramProvider.ts index 3c8f96a1f2..5480ee6160 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, ProgramWithName } from "./plugins" import { Program } from "../generated" +import { programGetDirectExternalSources, programGetExternalSources } from "./node-utilities/Program" export class ProgramProvider { // TODO: migrate to wrappers instead of pointers @@ -30,19 +31,22 @@ export class ProgramProvider { static dumpDeps(program: Program): string { let seen = new Set() let queue: Program[] = [] - let result = `digraph "Deps" {` + let result = `digraph "Dependencies of ${program.absoluteName}" {` queue.push(program) while (queue.length > 0) { const current = queue.shift()! - const listed = listPrograms(current, defaultFilter) - listed.forEach(it => { - if (it.program.peer != current.peer) { - result += `"${current.fileName}" -> "${it.program.fileName}";\n` - if (!seen.has(it.program.peer)) { - seen.add(it.program.peer) - queue.push(it.program) + 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 += "}" diff --git a/ui2abc/libarkts/src/arkts-api/node-utilities/Program.ts b/ui2abc/libarkts/src/arkts-api/node-utilities/Program.ts index 4e80fbb30f..a9c7bad981 100644 --- a/ui2abc/libarkts/src/arkts-api/node-utilities/Program.ts +++ b/ui2abc/libarkts/src/arkts-api/node-utilities/Program.ts @@ -25,3 +25,10 @@ export function programGetExternalSources(program: Program): ExternalSource[] { (instance: KNativePointer) => new ExternalSource(instance) ) } + +export function programGetDirectExternalSources(program: Program): ExternalSource[] { + return acceptNativeObjectArrayResult( + global.es2panda._ProgramDirectExternalSources(global.context, program.peer), + (instance: KNativePointer) => new ExternalSource(instance) + ) +} diff --git a/ui2abc/libarkts/src/plugin-utils.ts b/ui2abc/libarkts/src/plugin-utils.ts index 91d8b54aab..8760cb4bd1 100644 --- a/ui2abc/libarkts/src/plugin-utils.ts +++ b/ui2abc/libarkts/src/plugin-utils.ts @@ -24,9 +24,10 @@ import { Program, inferVoidReturnType, ETSModule, - ProgramProvider + ProgramProvider, + BlockStatement } from "./arkts-api" -import { AstNode } from "./reexport-for-generated" +import { AstNode, KNativePointer } from "./reexport-for-generated" export interface RunTransformerContext { isMainProgram: boolean @@ -37,10 +38,46 @@ export interface RunTransformerHooks { onProgramTransformEnd?(ctx: RunTransformerContext): boolean } + +class ASTCacheEntry { + programToTree = new Map() + constructor() {} + find(program: Program): AstNode|undefined { + return this.programToTree.get(program.peer) + } + update(program: Program, ast: AstNode) { + this.programToTree.set(program.peer, ast.clone()) + } +} +class ASTCache { + cache = new Map() + find(transformer: ProgramTransformer, program: Program) : AstNode|undefined { + return this.cache.get(transformer)?.find(program) + } + update(transformer: ProgramTransformer, program: Program, ast: AstNode) { + let entry = this.cache.get(transformer) + if (!entry) { + entry = new ASTCacheEntry() + this.cache.set(transformer, entry) + } + entry.update(program, ast) + } +} + +let verbose = false + export function runTransformer(prog: Program, state: Es2pandaContextState, transform: ProgramTransformer, pluginContext: PluginContext, hooks: RunTransformerHooks = {}) { + if (verbose) console.log(`RUN TRANSFORMER on ${prog.absoluteName}`) + // Visit deps const provider = new ProgramProvider({ program: prog, name: `${arktsGlobal.packageName}.${arktsGlobal.filePathFromPackageRoot}` }) let currentProgram = provider.next() + let cache = pluginContext.parameter("ASTCache") + if (!cache) { + cache = new ASTCache() + pluginContext.setParameter("ASTCache", cache) + } + console.log(ProgramProvider.dumpDeps(currentProgram!.program)) while (currentProgram) { const runCtx: RunTransformerContext = { @@ -50,12 +87,20 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, trans hooks.onProgramTransformStart?.(runCtx) const ast = currentProgram.program.ast as ETSModule - console.log(`PROCESS [P] ${currentProgram.program.absoluteName}`) const importStorage = new ImportStorage(currentProgram.program, state == Es2pandaContextState.ES2PANDA_STATE_PARSED) stageSpecificPreFilters(ast, state) - transform?.(currentProgram.program, { isMainProgram: runCtx.isMainProgram, name: currentProgram.name, stage: state }, pluginContext) + if (verbose) + console.log(`TRANSFORM on ${currentProgram.program.absoluteName} main is ${runCtx.isMainProgram}`) + let transformed = cache.find(transform, currentProgram.program) + if (transformed) { + console.log(`REUSE CACHED FOR ${currentProgram.program.absoluteName}`) + currentProgram.program.setAst(transformed.clone() as BlockStatement) + } else { + transform(currentProgram.program, { isMainProgram: runCtx.isMainProgram, name: currentProgram.name, stage: state }, pluginContext) + cache.update(transform, currentProgram.program, currentProgram.program.ast) + } stageSpecificPostFilters(ast, state) setBaseOverloads(ast) importStorage.update() diff --git a/ui2abc/ui-plugins/src/checked-stage-plugin.ts b/ui2abc/ui-plugins/src/checked-stage-plugin.ts index 9e80c4e0b8..1d3f0b45ff 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(), -- Gitee From e18a28dccd0f79d381f943c9367161eb3bfc3d3a Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 5 Jun 2025 15:28:21 +0300 Subject: [PATCH 3/4] WIP Signed-off-by: Nikolay Igotti --- incremental/tools/panda/arkts/ui2abc | 2 +- ui2abc/libarkts/native/src/bridges.cc | 24 +++++++++++++++++++ ui2abc/libarkts/src/Es2pandaNativeModule.ts | 3 +++ .../libarkts/src/arkts-api/peers/AstNode.ts | 7 +++++- ui2abc/libarkts/src/plugin-utils.ts | 6 ++--- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/incremental/tools/panda/arkts/ui2abc b/incremental/tools/panda/arkts/ui2abc index e9c4652a40..d362852ba5 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 "$@" +echo PANDA_SDK_PATH=${PANDA_SDK_PATH:=$SCRIPT_DIR/../node_modules/@panda/sdk} 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 2bf7e80830..aeeb3c1400 100644 --- a/ui2abc/libarkts/native/src/bridges.cc +++ b/ui2abc/libarkts/native/src/bridges.cc @@ -342,3 +342,27 @@ KNativePointer impl_CreateSourceRange(KNativePointer context, KNativePointer sta return GetImpl()->CreateSourceRange(_context_, _start_, _end_); } KOALA_INTEROP_3(CreateSourceRange, KNativePointer, KNativePointer, KNativePointer, KNativePointer); + + +static es2panda_Context* currentContext = nullptr; +static es2panda_AstNode* currentNode = nullptr; + +static es2panda_AstNode* cloneSubtree(es2panda_Context* context, es2panda_AstNode* oldCurrent, es2panda_AstNode* newParent) { + es2panda_AstNode* newCurrent = GetImpl()->AstNodeClone(context, oldCurrent, newParent); + currentContext = context; + currentNode = newCurrent; + GetImpl()->AstNodeIterateConst(context, oldCurrent, [] (es2panda_AstNode* oldChild) -> void { + auto* newChild = cloneSubtree(currentContext, oldChild, currentNode); + //GetImpl()->AstNodeAddChild(currentContext, currentNode, newChild); + }); + currentContext = nullptr; + currentNode = nullptr; + return newCurrent; +} +KNativePointer impl_AstNodeDeepClone(KNativePointer context, KNativePointer receiver) +{ + const auto _context = reinterpret_cast(context); + const auto _receiver = reinterpret_cast(receiver); + return cloneSubtree(_context, _receiver, nullptr); +} +KOALA_INTEROP_2(AstNodeDeepClone, KNativePointer, KNativePointer, KNativePointer); diff --git a/ui2abc/libarkts/src/Es2pandaNativeModule.ts b/ui2abc/libarkts/src/Es2pandaNativeModule.ts index 35d3fd5c69..429903418d 100644 --- a/ui2abc/libarkts/src/Es2pandaNativeModule.ts +++ b/ui2abc/libarkts/src/Es2pandaNativeModule.ts @@ -40,6 +40,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") } diff --git a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts index 55fbcf5a0b..8b165ae51b 100644 --- a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts +++ b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts @@ -96,7 +96,12 @@ export abstract class AstNode extends ArktsObject { } public clone(): this { - return unpackNonNullableNode(global.generatedEs2panda._AstNodeClone(global.context, this.peer, this.parent.peer)); + return unpackNonNullableNode(global.generatedEs2panda._AstNodeClone( + global.context, this.peer, global.generatedEs2panda._AstNodeParent(global.context, this.peer))) + } + + public deepClone(): this { + return unpackNonNullableNode(global.es2panda._AstNodeDeepClone(global.context, this.peer)) } public get parent(): AstNode { diff --git a/ui2abc/libarkts/src/plugin-utils.ts b/ui2abc/libarkts/src/plugin-utils.ts index 8760cb4bd1..6a56af7aba 100644 --- a/ui2abc/libarkts/src/plugin-utils.ts +++ b/ui2abc/libarkts/src/plugin-utils.ts @@ -46,7 +46,7 @@ class ASTCacheEntry { return this.programToTree.get(program.peer) } update(program: Program, ast: AstNode) { - this.programToTree.set(program.peer, ast.clone()) + this.programToTree.set(program.peer, ast.deepClone()) } } class ASTCache { @@ -77,8 +77,6 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, trans cache = new ASTCache() pluginContext.setParameter("ASTCache", cache) } - console.log(ProgramProvider.dumpDeps(currentProgram!.program)) - while (currentProgram) { const runCtx: RunTransformerContext = { isMainProgram: currentProgram.program.peer == prog.peer @@ -96,7 +94,7 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, trans let transformed = cache.find(transform, currentProgram.program) if (transformed) { console.log(`REUSE CACHED FOR ${currentProgram.program.absoluteName}`) - currentProgram.program.setAst(transformed.clone() as BlockStatement) + currentProgram.program.setAst(transformed.deepClone() as BlockStatement) } else { transform(currentProgram.program, { isMainProgram: runCtx.isMainProgram, name: currentProgram.name, stage: state }, pluginContext) cache.update(transform, currentProgram.program, currentProgram.program.ast) -- Gitee From e2b214f50ffa2357952b2053ec6937be9eb1a86a Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 5 Jun 2025 16:26:38 +0300 Subject: [PATCH 4/4] Update --- incremental/tools/panda/arkts/ui2abc | 2 +- ui2abc/libarkts/native/src/bridges.cc | 4 +++- .../libarkts/src/arkts-api/peers/AstNode.ts | 4 ++-- ui2abc/libarkts/src/plugin-utils.ts | 22 ++++++++++++++++--- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/incremental/tools/panda/arkts/ui2abc b/incremental/tools/panda/arkts/ui2abc index d362852ba5..e9c4652a40 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]}"` -echo 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} 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 aeeb3c1400..0d454e70d0 100644 --- a/ui2abc/libarkts/native/src/bridges.cc +++ b/ui2abc/libarkts/native/src/bridges.cc @@ -363,6 +363,8 @@ KNativePointer impl_AstNodeDeepClone(KNativePointer context, KNativePointer rece { const auto _context = reinterpret_cast(context); const auto _receiver = reinterpret_cast(receiver); - return cloneSubtree(_context, _receiver, nullptr); + auto result = GetImpl()->AstNodeClone(_context, _receiver, _receiver); // cloneSubtree(_context, _receiver, nullptr); + //printf("CLONED %s\n", GetImpl()->AstNodeDumpJSONConst(_context, result)); + return result; } KOALA_INTEROP_2(AstNodeDeepClone, KNativePointer, KNativePointer, KNativePointer); diff --git a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts index 8b165ae51b..c00f242496 100644 --- a/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts +++ b/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts @@ -95,9 +95,9 @@ export abstract class AstNode extends ArktsObject { return unpackString(global.es2panda._AstNodeDumpModifiers(global.context, this.peer)) } - public clone(): this { + public clone(parent: KNativePointer = nullptr): this { return unpackNonNullableNode(global.generatedEs2panda._AstNodeClone( - global.context, this.peer, global.generatedEs2panda._AstNodeParent(global.context, this.peer))) + global.context, this.peer, parent)) } public deepClone(): this { diff --git a/ui2abc/libarkts/src/plugin-utils.ts b/ui2abc/libarkts/src/plugin-utils.ts index 6a56af7aba..4339bf1ee3 100644 --- a/ui2abc/libarkts/src/plugin-utils.ts +++ b/ui2abc/libarkts/src/plugin-utils.ts @@ -25,9 +25,12 @@ import { inferVoidReturnType, ETSModule, ProgramProvider, - BlockStatement + BlockStatement, + AbstractVisitor, + isBlockStatement } from "./arkts-api" import { AstNode, KNativePointer } from "./reexport-for-generated" +import { factory } from "./arkts-api/factory/nodeFactory" export interface RunTransformerContext { isMainProgram: boolean @@ -38,6 +41,18 @@ export interface RunTransformerHooks { onProgramTransformEnd?(ctx: RunTransformerContext): boolean } +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 ASTCacheEntry { programToTree = new Map() @@ -46,7 +61,7 @@ class ASTCacheEntry { return this.programToTree.get(program.peer) } update(program: Program, ast: AstNode) { - this.programToTree.set(program.peer, ast.deepClone()) + this.programToTree.set(program.peer, deepClone(ast)) } } class ASTCache { @@ -94,8 +109,9 @@ export function runTransformer(prog: Program, state: Es2pandaContextState, trans let transformed = cache.find(transform, currentProgram.program) if (transformed) { console.log(`REUSE CACHED FOR ${currentProgram.program.absoluteName}`) - currentProgram.program.setAst(transformed.deepClone() as BlockStatement) + currentProgram.program.setAst(deepClone(transformed) as BlockStatement) } else { + console.log(`NO CACHE FOR ${currentProgram.program.absoluteName}`) transform(currentProgram.program, { isMainProgram: runCtx.isMainProgram, name: currentProgram.name, stage: state }, pluginContext) cache.update(transform, currentProgram.program, currentProgram.program.ast) } -- Gitee