From 2354b0f927c752a59512c2bf1894a8c0ac2502ca Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Fri, 21 Feb 2025 19:27:07 +0300 Subject: [PATCH 1/5] Compute --- arkoala-arkts/memo-plugin/src/FunctionTransformer.ts | 9 ++++++++- arkoala-arkts/memo-plugin/src/MemoFactory.ts | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts index 932170129..b28e71bcc 100644 --- a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts @@ -140,9 +140,16 @@ export class FunctionTransformer extends AbstractVisitor { const expr = node.expression const decl = arkts.getDecl(expr) if (decl instanceof arkts.MethodDefinition && hasMemoAnnotation(decl.scriptFunction)) { + decl.scriptFunction.parameters.forEach((it) => { + console.log(hasMemoAnnotation(it)) + }) const updatedArguments = node.arguments.map((it, index) => { if (hasMemoAnnotation(decl.scriptFunction.parameters[index])) { - return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) + if (it instanceof arkts.ArrowFunctionExpression) { + return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) + } else { + throw "ArrowFunctionExpression expected for @memo parameter" + } } return it }) diff --git a/arkoala-arkts/memo-plugin/src/MemoFactory.ts b/arkoala-arkts/memo-plugin/src/MemoFactory.ts index 5c9246d91..ded7e94f9 100644 --- a/arkoala-arkts/memo-plugin/src/MemoFactory.ts +++ b/arkoala-arkts/memo-plugin/src/MemoFactory.ts @@ -190,7 +190,7 @@ export class factory { ) ) } - static createComputeExpression(hash: arkts.NumberLiteral | arkts.StringLiteral, node: arkts.AstNode): arkts.CallExpression { + static createComputeExpression(hash: arkts.NumberLiteral | arkts.StringLiteral, node: arkts.ArrowFunctionExpression): arkts.CallExpression { return arkts.factory.createCallExpression( arkts.factory.createMemberExpression( arkts.factory.createIdentifier(RuntimeNames.CONTEXT), -- Gitee From 37bc589d5c025747dbae0e7f1af7d7e96e94ea8e Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Fri, 21 Feb 2025 19:31:49 +0300 Subject: [PATCH 2/5] remove logging --- arkoala-arkts/memo-plugin/src/FunctionTransformer.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts index b28e71bcc..580a66cdc 100644 --- a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts @@ -140,9 +140,6 @@ export class FunctionTransformer extends AbstractVisitor { const expr = node.expression const decl = arkts.getDecl(expr) if (decl instanceof arkts.MethodDefinition && hasMemoAnnotation(decl.scriptFunction)) { - decl.scriptFunction.parameters.forEach((it) => { - console.log(hasMemoAnnotation(it)) - }) const updatedArguments = node.arguments.map((it, index) => { if (hasMemoAnnotation(decl.scriptFunction.parameters[index])) { if (it instanceof arkts.ArrowFunctionExpression) { -- Gitee From 7c32c35c4f6abff3e2d88d52a825e168d634affe Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Fri, 21 Feb 2025 20:58:17 +0300 Subject: [PATCH 3/5] less strict @memo parameter check --- arkoala-arkts/memo-plugin/src/FunctionTransformer.ts | 6 +----- arkoala-arkts/memo-plugin/src/MemoFactory.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts index 580a66cdc..932170129 100644 --- a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts @@ -142,11 +142,7 @@ export class FunctionTransformer extends AbstractVisitor { if (decl instanceof arkts.MethodDefinition && hasMemoAnnotation(decl.scriptFunction)) { const updatedArguments = node.arguments.map((it, index) => { if (hasMemoAnnotation(decl.scriptFunction.parameters[index])) { - if (it instanceof arkts.ArrowFunctionExpression) { - return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) - } else { - throw "ArrowFunctionExpression expected for @memo parameter" - } + return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) } return it }) diff --git a/arkoala-arkts/memo-plugin/src/MemoFactory.ts b/arkoala-arkts/memo-plugin/src/MemoFactory.ts index ded7e94f9..5c9246d91 100644 --- a/arkoala-arkts/memo-plugin/src/MemoFactory.ts +++ b/arkoala-arkts/memo-plugin/src/MemoFactory.ts @@ -190,7 +190,7 @@ export class factory { ) ) } - static createComputeExpression(hash: arkts.NumberLiteral | arkts.StringLiteral, node: arkts.ArrowFunctionExpression): arkts.CallExpression { + static createComputeExpression(hash: arkts.NumberLiteral | arkts.StringLiteral, node: arkts.AstNode): arkts.CallExpression { return arkts.factory.createCallExpression( arkts.factory.createMemberExpression( arkts.factory.createIdentifier(RuntimeNames.CONTEXT), -- Gitee From 1de911458b537fb94bcccbba89250704f3db42e0 Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Mon, 24 Feb 2025 13:54:32 +0300 Subject: [PATCH 4/5] Draft --- .../src/arkts-api/factory/nodeFactory.ts | 7 ++ arkoala-arkts/libarkts/src/arkts-api/types.ts | 18 ++++ arkoala-arkts/memo-plugin/demo/demo.sts | 11 ++- arkoala-arkts/memo-plugin/demo/demo.ts | 9 ++ .../memo-plugin/src/FunctionTransformer.ts | 99 ++++++++++++------- arkoala-arkts/memo-plugin/src/MemoFactory.ts | 14 +++ .../memo-plugin/src/MemoTransformer.ts | 2 +- .../memo-plugin/src/ParameterTransformer.ts | 29 +++++- arkoala-arkts/memo-plugin/src/utils.ts | 13 +++ 9 files changed, 160 insertions(+), 42 deletions(-) diff --git a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts index eb99b8552..98ca70798 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts @@ -33,6 +33,7 @@ import { ExpressionStatement, FunctionDeclaration, FunctionExpression, + FunctionSignature, Identifier, IfStatement, ImportSpecifier, @@ -300,4 +301,10 @@ export const factory = { get updateAnnotationUsageIr() { return compose(UndefinedLiteral.create) }, + get createFunctionSignature() { + return FunctionSignature.create + }, + get updateFunctionSignature() { + return compose(UndefinedLiteral.create) + }, } diff --git a/arkoala-arkts/libarkts/src/arkts-api/types.ts b/arkoala-arkts/libarkts/src/arkts-api/types.ts index b04cc52b5..7ead28e93 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/types.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/types.ts @@ -364,6 +364,14 @@ export class ETSFunctionType extends AstNode { ) ) } + + get params() { + return unpackNodeArray(global.generatedEs2panda._ETSFunctionTypeIrParamsConst(global.context, this.peer)) + } + + get returnType() { + return unpackNode(global.generatedEs2panda._ETSFunctionTypeIrReturnType(global.context, this.peer)) + } } export class Identifier extends Expression { @@ -757,6 +765,16 @@ export class ETSParameterExpression extends AstNode { ); } + get type(): AstNode | undefined { + return unpackNode(global.generatedEs2panda._ETSParameterExpressionTypeAnnotation(global.context, this.peer)) + } + + set type(t: AstNode | undefined) { + if (t === undefined) + return + global.generatedEs2panda._ETSParameterExpressionSetTypeAnnotation(global.context, this.peer, t.peer) + } + identifier: Identifier } diff --git a/arkoala-arkts/memo-plugin/demo/demo.sts b/arkoala-arkts/memo-plugin/demo/demo.sts index 8e49383b9..8012d9510 100644 --- a/arkoala-arkts/memo-plugin/demo/demo.sts +++ b/arkoala-arkts/memo-plugin/demo/demo.sts @@ -1,4 +1,4 @@ -import { GlobalStateManager, memoEntry, StateContext, memo } from "@koalaui/runtime" +import { GlobalStateManager, memoEntry, StateContext, memo, memo_intrinsic } from "@koalaui/runtime" import { memo_foo } from "./stub" @memo @@ -13,10 +13,19 @@ function f(s: string) { y("she") } +@memo +function bar( + arg1: number, + @memo arg2: (x: number) => number, +) { + console.log(arg1, arg2(arg1)) +} + @memo function foo_wrapper() { ETSGLOBAL.f("he") memo_foo("hello") + ETSGLOBAL.bar(1, (x: number): number => { return 3 + x; }) } function main() { diff --git a/arkoala-arkts/memo-plugin/demo/demo.ts b/arkoala-arkts/memo-plugin/demo/demo.ts index 1d5af0733..7e4d48536 100644 --- a/arkoala-arkts/memo-plugin/demo/demo.ts +++ b/arkoala-arkts/memo-plugin/demo/demo.ts @@ -16,10 +16,19 @@ function f(s: string) { y("she") } +/** @memo */ +function bar( + arg1: number, + /** @memo */ arg2: (x: number) => number, +) { + console.log(arg1, arg2(arg1)) +} + /** @memo */ function foo_wrapper() { f("he") memo_foo("hello") + bar(1, (x: number): number => { return 3 + x; }) } function main() { diff --git a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts index 932170129..bdb4b0ee6 100644 --- a/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/FunctionTransformer.ts @@ -18,17 +18,12 @@ import { factory } from "./MemoFactory" import { AbstractVisitor } from "./AbstractVisitor" import { PositionalIdTracker, - RuntimeNames + hasMemoAnnotation, + hasMemoIntrinsicAnnotation, } from "./utils" import { ParameterTransformer } from "./ParameterTransformer" import { ReturnTransformer } from "./ReturnTranformer" -function hasMemoAnnotation(node: arkts.ScriptFunction | arkts.ETSParameterExpression) { - return node.annotations.some((it) => - it.expr !== undefined && arkts.isIdentifier(it.expr) && it.expr.name === RuntimeNames.ANNOTATION - ) -} - function updateFunctionBody( node: arkts.BlockStatement, parameters: arkts.ETSParameterExpression[], @@ -93,43 +88,71 @@ export class FunctionTransformer extends AbstractVisitor { super() } + updateScriptFunction( + scriptFunction: arkts.ScriptFunction, + name: string = "", + ): arkts.ScriptFunction { + if (!scriptFunction.body) { + return scriptFunction + } + const [body, memoParametersDeclaration, syntheticReturnStatement] = updateFunctionBody( + scriptFunction.body, + scriptFunction.parameters, + scriptFunction.returnTypeAnnotation, + this.positionalIdTracker.id(name), + ) + const afterParameterTransformer = this.parameterTransformer + .withParameters(scriptFunction.parameters) + .skip(memoParametersDeclaration) + .visitor(body) + const afterReturnTransformer = this.returnTransformer + .skip(syntheticReturnStatement) + .visitor(afterParameterTransformer) + const updatedParameters = scriptFunction.parameters.map((param) => { + if (hasMemoAnnotation(param)) { + if (!(param.type instanceof arkts.ETSFunctionType)) { + throw "ArrowFunctionExpression expected for @memo parameter of @memo_intrinsic function" + } + param.type = arkts.factory.createFunctionType( + arkts.factory.createFunctionSignature( + undefined, + [...factory.createHiddenParameters(), ...param.type.params], + param.type.returnType, + ), + arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW, + ) + } + return param + }) + return arkts.factory.updateScriptFunction( + scriptFunction, + afterReturnTransformer, + scriptFunction.scriptFunctionFlags, + scriptFunction.modifiers, + false, + scriptFunction.ident, + [...factory.createHiddenParameters(), ...updatedParameters], + scriptFunction.typeParamsDecl, + scriptFunction.returnTypeAnnotation + ) + } + visitor(beforeChildren: arkts.AstNode): arkts.AstNode { // TODO: Remove (currently annotations are lost on visitor) const methodDefinitionHasMemoAnnotation = beforeChildren instanceof arkts.MethodDefinition && hasMemoAnnotation(beforeChildren.scriptFunction) + const methodDefinitionHasMemoIntrinsicAnnotation = + beforeChildren instanceof arkts.MethodDefinition && hasMemoIntrinsicAnnotation(beforeChildren.scriptFunction) const node = this.visitEachChild(beforeChildren) if (node instanceof arkts.MethodDefinition && node.scriptFunction.body) { - if (methodDefinitionHasMemoAnnotation) { - const [body, memoParametersDeclaration, syntheticReturnStatement] = updateFunctionBody( - node.scriptFunction.body, - node.scriptFunction.parameters, - node.scriptFunction.returnTypeAnnotation, - this.positionalIdTracker.id(node.name.name), - ) - const afterParameterTransformer = this.parameterTransformer - .withParameters(node.scriptFunction.parameters) - .skip(memoParametersDeclaration) - .visitor(body) - const afterReturnTransformer = this.returnTransformer - .skip(syntheticReturnStatement) - .visitor(afterParameterTransformer) + if (methodDefinitionHasMemoAnnotation || methodDefinitionHasMemoIntrinsicAnnotation) { return arkts.factory.updateMethodDefinition( node, arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, node.name, arkts.factory.createFunctionExpression( - arkts.factory.updateScriptFunction( - node.scriptFunction, - afterReturnTransformer, - node.scriptFunction.scriptFunctionFlags, - node.scriptFunction.modifiers, - false, - node.scriptFunction.ident, - [...factory.createHiddenParameters(), ...node.scriptFunction.parameters], - node.scriptFunction.typeParamsDecl, - node.scriptFunction.returnTypeAnnotation - ) + this.updateScriptFunction(node.scriptFunction, node.name.name), ), node.modifiers, false @@ -139,10 +162,16 @@ export class FunctionTransformer extends AbstractVisitor { if (node instanceof arkts.CallExpression) { const expr = node.expression const decl = arkts.getDecl(expr) - if (decl instanceof arkts.MethodDefinition && hasMemoAnnotation(decl.scriptFunction)) { + if (decl instanceof arkts.MethodDefinition && (hasMemoAnnotation(decl.scriptFunction) || hasMemoIntrinsicAnnotation(decl.scriptFunction))) { const updatedArguments = node.arguments.map((it, index) => { - if (hasMemoAnnotation(decl.scriptFunction.parameters[index])) { - return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) + if (decl.scriptFunction.parameters[index].type instanceof arkts.ETSFunctionType) { + if (!hasMemoAnnotation(decl.scriptFunction.parameters[index]) && !hasMemoIntrinsicAnnotation(decl.scriptFunction.parameters[index])) { + return factory.createComputeExpression(this.positionalIdTracker.id(decl.name.name), it) + } + if (!(it instanceof arkts.ArrowFunctionExpression)) { + throw "ArrowFunctionExpression expected for @memo argument of @memo function" + } + return this.updateScriptFunction(it.scriptFunction) } return it }) diff --git a/arkoala-arkts/memo-plugin/src/MemoFactory.ts b/arkoala-arkts/memo-plugin/src/MemoFactory.ts index 5c9246d91..e83ea086d 100644 --- a/arkoala-arkts/memo-plugin/src/MemoFactory.ts +++ b/arkoala-arkts/memo-plugin/src/MemoFactory.ts @@ -108,6 +108,20 @@ export class factory { false, ) } + static createMemoParameterAccessMemo(name: string, hash: arkts.NumberLiteral | arkts.StringLiteral, passArgs?: arkts.AstNode[]): arkts.CallExpression { + const updatedArgs = passArgs ? passArgs : [] + return arkts.factory.createCallExpression( + arkts.factory.createMemberExpression( + factory.createMemoParameterIdentifier(name), + arkts.factory.createIdentifier(RuntimeNames.VALUE), + arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_GETTER, + false, + false, + ), + undefined, + [...factory.createHiddenArguments(hash), ...updatedArgs], + ) + } // Recache static createScopeDeclaration(returnTypeAnnotation: arkts.AstNode | undefined, hash: arkts.NumberLiteral | arkts.StringLiteral, cnt: number): arkts.VariableDeclaration { diff --git a/arkoala-arkts/memo-plugin/src/MemoTransformer.ts b/arkoala-arkts/memo-plugin/src/MemoTransformer.ts index 8ac6ee906..876720259 100644 --- a/arkoala-arkts/memo-plugin/src/MemoTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/MemoTransformer.ts @@ -29,7 +29,7 @@ export default function memoTransformer( ) { return (node: arkts.EtsScript) => { const positionalIdTracker = new PositionalIdTracker(arkts.getFileName(), false) - const parameterTransformer = new ParameterTransformer() + const parameterTransformer = new ParameterTransformer(positionalIdTracker) const returnTransformer = new ReturnTransformer() const functionTransformer = new FunctionTransformer(positionalIdTracker, parameterTransformer, returnTransformer) return functionTransformer.visitor( diff --git a/arkoala-arkts/memo-plugin/src/ParameterTransformer.ts b/arkoala-arkts/memo-plugin/src/ParameterTransformer.ts index cf4d874e3..eaf6fb289 100644 --- a/arkoala-arkts/memo-plugin/src/ParameterTransformer.ts +++ b/arkoala-arkts/memo-plugin/src/ParameterTransformer.ts @@ -17,15 +17,24 @@ import * as arkts from "@koalaui/libarkts" import { factory } from "./MemoFactory" import { AbstractVisitor } from "./AbstractVisitor" import { KPointer } from "@koalaui/interop" -import { isMemoParametersDeclaration } from "./utils" +import { hasMemoAnnotation, hasMemoIntrinsicAnnotation, isMemoParametersDeclaration, PositionalIdTracker } from "./utils" export class ParameterTransformer extends AbstractVisitor { - private rewrites?: Map arkts.MemberExpression> + private rewrites?: Map arkts.CallExpression | arkts.MemberExpression> private skipNode?: arkts.VariableDeclaration + constructor(private positionalIdTracker: PositionalIdTracker) { + super() + } + withParameters(parameters: arkts.ETSParameterExpression[]): ParameterTransformer { this.rewrites = new Map(parameters.map((it) => { - return [it.peer, () => factory.createMemoParameterAccess(it.identifier.name)] + return [it.peer, (passArgs?: arkts.AstNode[]) => { + if (hasMemoAnnotation(it) || hasMemoIntrinsicAnnotation(it)) { + return factory.createMemoParameterAccessMemo(it.identifier.name, this.positionalIdTracker?.id(""), passArgs) + } + return factory.createMemoParameterAccess(it.identifier.name) + }] })) return this } @@ -41,11 +50,21 @@ export class ParameterTransformer extends AbstractVisitor { if (/* beforeChildren === this.skipNode */ isMemoParametersDeclaration(beforeChildren)) { return beforeChildren } + if (beforeChildren instanceof arkts.CallExpression) { + if (beforeChildren.expression instanceof arkts.Identifier) { + const decl = arkts.getDecl(beforeChildren.expression) + if (decl instanceof arkts.ETSParameterExpression && this.rewrites?.has(decl.peer)) { + return this.rewrites.get(decl.peer)!( + beforeChildren.arguments.map((it) => this.visitor(it)) + ) + } + } + } const node = this.visitEachChild(beforeChildren) if (node instanceof arkts.Identifier) { const decl = arkts.getDecl(node) - if (decl instanceof arkts.ETSParameterExpression && this.rewrites?.get(decl.peer)) { - return this.rewrites.get(decl.peer)?.() ?? node + if (decl instanceof arkts.ETSParameterExpression && this.rewrites?.has(decl.peer)) { + return this.rewrites.get(decl.peer)!() } } return node diff --git a/arkoala-arkts/memo-plugin/src/utils.ts b/arkoala-arkts/memo-plugin/src/utils.ts index d936ba040..fd1cd4691 100644 --- a/arkoala-arkts/memo-plugin/src/utils.ts +++ b/arkoala-arkts/memo-plugin/src/utils.ts @@ -20,6 +20,7 @@ export enum RuntimeNames { __CONTEXT = "__context", __ID = "__id", ANNOTATION = "memo", + ANNOTATION_INTRINSIC = "memo_intrinsic", COMPUTE = "compute", CONTEXT = "__memo_context", CONTEXT_TYPE = "__memo_context_type", @@ -81,6 +82,18 @@ export class PositionalIdTracker { } } +export function hasMemoAnnotation(node: arkts.ScriptFunction | arkts.ETSParameterExpression) { + return node.annotations.some((it) => + it.expr !== undefined && arkts.isIdentifier(it.expr) && it.expr.name === RuntimeNames.ANNOTATION + ) +} + +export function hasMemoIntrinsicAnnotation(node: arkts.ScriptFunction | arkts.ETSParameterExpression) { + return node.annotations.some((it) => + it.expr !== undefined && arkts.isIdentifier(it.expr) && it.expr.name === RuntimeNames.ANNOTATION_INTRINSIC + ) +} + /** * TODO: * @deprecated -- Gitee From 6faa0676159ec573103e1d0e6d344d3360eca58f Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Mon, 24 Feb 2025 12:52:18 +0000 Subject: [PATCH 5/5] update arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts. Signed-off-by: Igor Loginov --- arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts index 98ca70798..fb5e4f0ef 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts @@ -304,7 +304,4 @@ export const factory = { get createFunctionSignature() { return FunctionSignature.create }, - get updateFunctionSignature() { - return compose(UndefinedLiteral.create) - }, } -- Gitee