From 65a4f58b581b4a8f34f631631af48fcba7d5e49d Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Fri, 21 Feb 2025 21:59:40 +0300 Subject: [PATCH 1/2] Attempt to put demo-playground into memo-plugin --- arkoala-arkts/libarkts/src/arkts-api/types.ts | 2 +- .../libarkts/src/arkts-api/visitor.ts | 7 ++ arkoala-arkts/memo-plugin/demo/demo.sts | 82 ++++++++++++++++++- arkoala-arkts/memo-plugin/demo/demo.ts | 64 ++++++++++++++- 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/arkoala-arkts/libarkts/src/arkts-api/types.ts b/arkoala-arkts/libarkts/src/arkts-api/types.ts index 2b48b844d2..479485670f 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/types.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/types.ts @@ -1140,7 +1140,7 @@ export class SuperExpression extends AstNode { constructor(peer: KPtr) { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_SUPER_EXPRESSION) super(peer) - this.id = unpackNonNullableNode(global.generatedEs2panda._TSInterfaceDeclarationId(global.context, this.peer)); + this.id = unpackNode(global.generatedEs2panda._TSInterfaceDeclarationId(global.context, this.peer)); } static create( diff --git a/arkoala-arkts/libarkts/src/arkts-api/visitor.ts b/arkoala-arkts/libarkts/src/arkts-api/visitor.ts index 6d518991d6..dde49b9727 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/visitor.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/visitor.ts @@ -15,6 +15,7 @@ import { factory } from "./factory/nodeFactory" import { + ArrowFunctionExpression, BlockStatement, CallExpression, ClassDeclaration, @@ -250,6 +251,12 @@ export function visitEachChild( nodeVisitor(node.alternate, visitor), ) } + if (node instanceof ArrowFunctionExpression) { + return factory.updateArrowFunction( + node, + nodeVisitor(node.scriptFunction, visitor) + ) + } // TODO return node } diff --git a/arkoala-arkts/memo-plugin/demo/demo.sts b/arkoala-arkts/memo-plugin/demo/demo.sts index 8e49383b95..a133926166 100644 --- a/arkoala-arkts/memo-plugin/demo/demo.sts +++ b/arkoala-arkts/memo-plugin/demo/demo.sts @@ -1,4 +1,5 @@ -import { GlobalStateManager, memoEntry, StateContext, memo } from "@koalaui/runtime" +import { GlobalStateManager, memoEntry, StateContext, IncrementalNode, NodeAttach, + mutableState, contextLocalValue, ReadonlyTreeNode, CONTEXT_ROOT_SCOPE, memoRoot, updateStateManager, memo } from "@koalaui/runtime" import { memo_foo } from "./stub" @memo @@ -19,6 +20,68 @@ function foo_wrapper() { memo_foo("hello") } +/* +TODO: +1. ETSGLOBAL +2. return type of type parametrized stuff such +3. context?.() +4. losing default arguments +5. optional parameters results in T|undefined|undefined... (and become not optional) +6. weird runtime error if trying to compile with fixes 1-5 + - if section A is commented out, error happens after checked stage + - if section A is not commented out, error happes on checked stage + +class StringerNode extends IncrementalNode { + constructor(kind: int = 1) { // 4 + super(kind) + } + data: string | undefined = undefined +} + +@memo +function Stringer( + arg: string, + @memo + content?: () => void +): void { + NodeAttach((): StringerNode => new StringerNode(1), (node: StringerNode): void => { // 2, 4 + node.data = arg + console.log("I am recomputing with arg: ", arg) + content ? content() : undefined // 3 + }) +} + +const global_state = mutableState(17) + +@memo +function demo(node: StringerNode): void { + ETSGLOBAL.Stringer("First", () => { + console.log("Content of the first") + + // Section A + // ETSGLOBAL.Stringer(`Second ${ETSGLOBAL.global_state.value}`, () => { + // console.log("Content of the second") + // ETSGLOBAL.Stringer("Third", undefined) // 6 + // }) + // ETSGLOBAL.Stringer("Fourth", () => { + // console.log("Content of the 4th") + // ETSGLOBAL.Stringer("5th", undefined) + // }) + }) + + // This is to dump the complete managed incremental scope tree + const scope = contextLocalValue(CONTEXT_ROOT_SCOPE) + console.log(scope ? scope.toHierarchy() : undefined) // 3 +} +*/ + +/* +function test1() { console.log(123) } +@memo function test2(@memo arg: () => void) { } +@memo function test3() { ETSGLOBAL.test2(() => { console.log(123) }) } +@memo function test4() { ETSGLOBAL.test2(ETSGLOBAL.test1) } // results in unreadable binary +*/ + function main() { const manager = GlobalStateManager.instance const state = manager.computableState((context: StateContext): Int => { @@ -26,4 +89,21 @@ function main() { return 20 }) console.log(state.value) + + /* + // memoRoot is the entry point here. + // It initializes the incremental runtime and computes the first frame. + // Have a look at its implementation. + const root = memoRoot(new StringerNode(0), ETSGLOBAL.demo) + console.log(root.value.toHierarchy()) // dump ui subtree + + updateStateManager() // Compute next frame. + console.log(root.value.toHierarchy()) + + ETSGLOBAL.global_state.value = 19 + + updateStateManager() // Compute the next frame. + console.log(root.value.toHierarchy()) + console.log("-----END-----") + */ } diff --git a/arkoala-arkts/memo-plugin/demo/demo.ts b/arkoala-arkts/memo-plugin/demo/demo.ts index 1d5af07338..5af71edf86 100644 --- a/arkoala-arkts/memo-plugin/demo/demo.ts +++ b/arkoala-arkts/memo-plugin/demo/demo.ts @@ -1,7 +1,8 @@ // This file is needed to check how unmemoized (by ts plugin) should look like // It is not actually executed -import { GlobalStateManager, memoEntry, StateContext } from "@koalaui/runtime" +import { GlobalStateManager, memoEntry, StateContext, IncrementalNode, NodeAttach, + mutableState, contextLocalValue, ReadonlyTreeNode, CONTEXT_ROOT_SCOPE, memoRoot, updateStateManager } from "@koalaui/runtime" import { memo_foo } from "./stub" /** @memo */ @@ -22,6 +23,52 @@ function foo_wrapper() { memo_foo("hello") } +class StringerNode extends IncrementalNode { + constructor(kind: number = 1) { + super(kind) + } + data: string | undefined = undefined +} + +/** @memo */ +function Stringer( + arg: string, + /** @memo */ + content?: () => void +): void { + NodeAttach(() => new StringerNode(), (node: StringerNode): void => { + node.data = arg + console.log("I am recomputing with arg: ", arg) + content?.() + }) +} + +const global_state = mutableState(17) + +/** @memo */ +function demo(node: StringerNode): void { + Stringer("First", () => { + console.log("Content of the first") + Stringer(`Second ${global_state.value}`, () => { + console.log("Content of the second") + Stringer("Third") + }) + Stringer("Fourth", () => { + console.log("Content of the 4th") + Stringer("5th") + }) + }) + + // This is to dump the complete managed incremental scope tree + const scope = contextLocalValue(CONTEXT_ROOT_SCOPE) + console.log(scope?.toHierarchy()) +} + +function test1() { console.log(123) } +/** @memo */ function test2(/** @memo */ arg: () => void) { } +/** @memo */ function test3() { test2(() => { console.log(123) }) } +/** @memo */ function test4() { test2(test1) } + function main() { const manager = GlobalStateManager.instance const state = manager.computableState((context: StateContext) => { @@ -29,4 +76,19 @@ function main() { return 20 }) console.log(state.value) + + // memoRoot is the entry point here. + // It initializes the incremental runtime and computes the first frame. + // Have a look at its implementation. + const root = memoRoot(new StringerNode(0), demo) + console.log(root.value.toHierarchy()) // dump ui subtree + + updateStateManager() // Compute next frame. + console.log(root.value.toHierarchy()) + + global_state.value = 19 + + updateStateManager() // Compute the next frame. + console.log(root.value.toHierarchy()) + console.log("-----END-----") } -- Gitee From a7e4b26fdd7089a03933dd53051aa40d67fc4924 Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Fri, 21 Feb 2025 22:10:21 +0300 Subject: [PATCH 2/2] A bit more readable --- arkoala-arkts/memo-plugin/demo/demo.sts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arkoala-arkts/memo-plugin/demo/demo.sts b/arkoala-arkts/memo-plugin/demo/demo.sts index a133926166..c86980f73b 100644 --- a/arkoala-arkts/memo-plugin/demo/demo.sts +++ b/arkoala-arkts/memo-plugin/demo/demo.sts @@ -23,8 +23,8 @@ function foo_wrapper() { /* TODO: 1. ETSGLOBAL -2. return type of type parametrized stuff such -3. context?.() +2. return type of type parametrized stuff such as function f(() => T) { } +3. content?.() 4. losing default arguments 5. optional parameters results in T|undefined|undefined... (and become not optional) 6. weird runtime error if trying to compile with fixes 1-5 @@ -61,7 +61,7 @@ function demo(node: StringerNode): void { // Section A // ETSGLOBAL.Stringer(`Second ${ETSGLOBAL.global_state.value}`, () => { // console.log("Content of the second") - // ETSGLOBAL.Stringer("Third", undefined) // 6 + // ETSGLOBAL.Stringer("Third", undefined) // 5 // }) // ETSGLOBAL.Stringer("Fourth", () => { // console.log("Content of the 4th") @@ -78,7 +78,7 @@ function demo(node: StringerNode): void { /* function test1() { console.log(123) } @memo function test2(@memo arg: () => void) { } -@memo function test3() { ETSGLOBAL.test2(() => { console.log(123) }) } +@memo function test3() { ETSGLOBAL.test2(() => { console.log(123) }) } // ok @memo function test4() { ETSGLOBAL.test2(ETSGLOBAL.test1) } // results in unreadable binary */ -- Gitee