diff --git a/arkoala-arkts/libarkts/.gitignore b/arkoala-arkts/libarkts/.gitignore index a54cdb4b371e117cc69c209347c065dbaa404be3..d37d63bfd0ca9c4d474a0a923b34459b7db19ae7 100644 --- a/arkoala-arkts/libarkts/.gitignore +++ b/arkoala-arkts/libarkts/.gitignore @@ -3,3 +3,6 @@ build* native/build-* native/*.ini lib +!test/es2panda/* +!test/golden/* +!compatible/src/* diff --git a/arkoala-arkts/libarkts/.mocha.json b/arkoala-arkts/libarkts/.mocha.json index 49d5f9382f46735d1ac5ce4b168c945def896be7..0068e6466395b1eceafa7b2e7c22428d4e9de4ab 100644 --- a/arkoala-arkts/libarkts/.mocha.json +++ b/arkoala-arkts/libarkts/.mocha.json @@ -2,5 +2,6 @@ "ui": "tdd", "spec": "./test/es2panda/**/*.test.ts", "extension": ["ts"], - "require": ["../../incremental/test-utils/scripts/register"] + "require": ["../../incremental/test-utils/scripts/register"], + "timeout": 10000 } diff --git a/arkoala-arkts/libarkts/arktsconfig.json b/arkoala-arkts/libarkts/arktsconfig.json index 8152e95b04850448ff47147c42f25fa72916a88e..fb3f0a8209ced7cfbdd009572879b74da18ab8ae 100644 --- a/arkoala-arkts/libarkts/arktsconfig.json +++ b/arkoala-arkts/libarkts/arktsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "baseUrl": "node_modules/@panda/sdk", + "baseUrl": "../../incremental/tools/panda/node_modules/@panda/sdk", "paths": { "std": [ "./ets/stdlib/std" @@ -11,8 +11,8 @@ }, "plugins": [ { - "transform": "./compatible/build_arkts/example-transformer.js" + "transform": "/home/huawei/arkcompiler_ets_frontend/arkoala-arkts/libarkts/compatible/src/example-transformer.ts" } ] } -} \ No newline at end of file +} diff --git a/arkoala-arkts/libarkts/src/arkts/util.ts b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts similarity index 49% rename from arkoala-arkts/libarkts/src/arkts/util.ts rename to arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts index 7bb42d13fee0a28721b2aaa5f12d962d782f43cf..3fd6bba01bc986c5b0a52f15bf643fe646ebc058 100644 --- a/arkoala-arkts/libarkts/src/arkts/util.ts +++ b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts @@ -13,6 +13,32 @@ * limitations under the License. */ -export function throwError(error: string): never { - throw new Error(error) +import * as arkts from "../../src/arkts" + +export abstract class AbstractVisitor { + constructor( + // public ctx: api.TransformationContext + ) {} + + indentation = 0 + + withIndentation(exec: () => T) { + this.indentation++ + const result = exec() + this.indentation-- + return result + } + + abstract visitor(node: arkts.Node): arkts.Node + + visitEachChild(node: T): T { + return this.withIndentation(() => + arkts.visitEachChild( + node, + it => this.visitor(it), + // this.ctx + ) + ) + } } + diff --git a/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..2ee3620560a45ec35c7c47e29225559784b862a6 --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as arkts from "../../src/arkts" +import { AbstractVisitor } from "./AbstractVisitor"; + +export class BuilderLambdaTransformer extends AbstractVisitor { + constructor( + // public tracer: Tracer, + // public sourceFile: api.SourceFile, + // public functionTable: FunctionTable, + // ctx: api.TransformationContext + ) { + // super(ctx) + super() + } + + private static readonly builderLambdaPrefix = "_BuilderLambdaCall_" + private static readonly builderLambdaInstanceName = "instance" + + private isBuilderLambdaCall(node: arkts.CallExpression): boolean { + if (!arkts.isIdentifier(node.expression)) { + return false + } + return node.expression.text.startsWith(BuilderLambdaTransformer.builderLambdaPrefix) + } + + visitor(beforeChildren: arkts.Node): arkts.Node { + const node: arkts.Node = this.visitEachChild(beforeChildren) + + if (!arkts.isCallExpression(node)) { + return node + } + + if (true + && arkts.isPropertyAccessExpression(node.parent) + && arkts.isIdentifier(node.parent.name) + && arkts.isCallExpression(node.parent.parent) + ) { + return node + } + + let instanceCalls = [] + let node1 = node + while (true + && arkts.isPropertyAccessExpression(node1.expression) + && arkts.isIdentifier(node1.expression.name) + && arkts.isCallExpression(node1.expression.expression) + ) { + instanceCalls.push( + arkts.factory.createCallExpression( + node1.expression.name, + undefined, + node1.arguments + ) + ) + node1 = node1.expression.expression + } + + if (!this.isBuilderLambdaCall(node1)) { + return node + } + + instanceCalls = instanceCalls.reverse() + let instanceLambdaBodyStatement: arkts.Identifier | arkts.CallExpression = arkts.factory.createIdentifier(BuilderLambdaTransformer.builderLambdaInstanceName) + instanceCalls.forEach(function (call: arkts.CallExpression) { + instanceLambdaBodyStatement = arkts.factory.createCallExpression( + arkts.factory.createPropertyAccessExpression( + instanceLambdaBodyStatement, + call.expression as arkts.Identifier + ), + undefined, + call.arguments + ) + }) + const instanceLambdaBody = arkts.factory.createBlock([ + arkts.factory.createReturnStatement( + instanceLambdaBodyStatement + ) + ]) + const instanceLambdaParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier( + BuilderLambdaTransformer.builderLambdaInstanceName, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + ) + ) + ] + const lambdaArg = arkts.factory.createArrowFunction( + undefined, + undefined, + instanceLambdaParams, + undefined, + undefined, + instanceLambdaBody + ) + + let funcName = (node1.expression as arkts.Identifier).text + funcName = funcName.slice(BuilderLambdaTransformer.builderLambdaPrefix.length) + + return arkts.factory.updateCallExpression( + node, + arkts.factory.updateIdentifier(node1.expression as arkts.Identifier, funcName), + undefined, + [ + lambdaArg, + ...node1.arguments + ] + ) + } +} diff --git a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts index a933bffa0fccac3acf224491d5fe26e0e278e7a8..4caaf26981d8afb54f78931d5b1b42714569de1d 100644 --- a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts @@ -1,15 +1,15 @@ -import * as api from "api" -import { PrintVisitor } from "./print-visitor" +import * as arkts from "../../src/arkts" +import { BuilderLambdaTransformer } from "./builder-lambda-transformer" export interface TransformerOptions { trace?: boolean, } -export default function exampleTransformer(program: api.Program, userPluginOptions: TransformerOptions) { - return (ctx: api.TransformationContext) => { - return (node: api.SourceFile) => { - console.log(new PrintVisitor().astToString(node)) - return node - } +// TODO: program(filePath) -> program: api.Program +export default function exampleTransformer(filePath: string): (node: arkts.SourceFile) => arkts.Node { + return (node: arkts.SourceFile) => { + const builderLambdaTransformer = new BuilderLambdaTransformer() + const transformed = builderLambdaTransformer.visitor(node) + return transformed } } diff --git a/arkoala-arkts/libarkts/compatible/src/function-transformer.ts b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae7e21d9716dc5006a34b28fc5607a50c9269b4c --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as arkts from "../../src/arkts" +import { AbstractVisitor } from "./AbstractVisitor"; + +const ANNOTATION = "_REWRITE_" + +function isAnnotatedCallExpression(node: arkts.Node): boolean { + return arkts.isCallExpression(node) && arkts.isIdentifier(node.expression) && node.expression.text.startsWith(ANNOTATION) +} + +function isAnnotatedMethodDeclaration(node: arkts.Node): boolean { + return arkts.isMethodDeclaration(node) && node.name.text.startsWith(ANNOTATION) +} + +function transformCallExpression(node: arkts.CallExpression): arkts.Node { + const decl = arkts.getDecl(node.expression) + if (decl === undefined) { + arkts.throwError('memo function not found') + } + if (!arkts.isIdentifier(node.expression)) { + arkts.throwError('expression should be Identifier') + } + + return arkts.factory.updateCallExpression( + node, + arkts.factory.updateIdentifier( + node.expression, + node.expression.text.slice(ANNOTATION.length) + ), + undefined, + [ + arkts.factory.createStringLiteral("SAMPLE"), + ...node.arguments + ] + ) +} + +function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { + const stringParam = + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier( + "x", + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + ) + ) + return arkts.factory.updateMethodDeclaration( + node, + undefined, + undefined, + arkts.factory.updateIdentifier( + node.name, + node.name.text.slice(ANNOTATION.length) + ), + undefined, + undefined, + [ + stringParam, + ...node.parameters + ], + undefined, + node.body, + ) +} + +export class FunctionTransformer extends AbstractVisitor { + constructor( + // public tracer: Tracer, + // public sourceFile: api.SourceFile, + // public functionTable: FunctionTable, + // ctx: api.TransformationContext + ) { + // super(ctx) + super() + } + + visitor(beforeChildren: arkts.Node): arkts.Node { + const node: arkts.Node = this.visitEachChild(beforeChildren) + + if (isAnnotatedMethodDeclaration(node) && arkts.isMethodDeclaration(node)) { + return transformMethodDeclaration(node) + } else if (isAnnotatedCallExpression(node) && arkts.isCallExpression(node) && arkts.isIdentifier(node.expression)) { + return transformCallExpression(node) + } + + return node + } +} diff --git a/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab3ce5c8b875a9deef1cac0b21c94172c85661a7 --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as arkts from "../../src/arkts" +import { AbstractVisitor } from "./AbstractVisitor"; + +const ANNOTATION = "_MEMO_" + +function isAnnotatedCallExpression(node: arkts.Node): boolean { + return arkts.isCallExpression(node) && arkts.isIdentifier(node.expression) && node.expression.text.startsWith(ANNOTATION) +} + +function isAnnotatedMethodDeclaration(node: arkts.Node): boolean { + return arkts.isMethodDeclaration(node) && node.name.text.startsWith(ANNOTATION) +} + +function transformCallExpression(node: arkts.CallExpression): arkts.Node { + const decl = arkts.getDecl(node.expression) + if (decl === undefined) { + arkts.throwError('memo function not found') + } + if (!arkts.isIdentifier(node.expression)) { + arkts.throwError('expression should be Identifier') + } + + return arkts.factory.updateCallExpression( + node, + arkts.factory.updateIdentifier( + node.expression, + node.expression.text.slice(ANNOTATION.length) + ), + undefined, + [ + arkts.factory.createIdentifier("__memo_context"), + arkts.factory.createIdentifier("__memo_id"), + ...node.arguments + ] + ) +} + +function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { + const memoContextParam = + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier( + "__memo_context", + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("__memo_context_type") + ) + ) + ) + const memoIdParam = + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier( + "__memo_id", + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("__memo_id_type") + ) + ) + ) + const bodyStatements = [ + arkts.factory.createIfStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("unchanged") + ), + arkts.factory.createReturnStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("cached") + ) + ), + undefined + ), + arkts.factory.createExpressionStatement( + arkts.factory.createCallExpression( + arkts.factory.createIdentifier("content"), + undefined, + [ + arkts.factory.createIdentifier("__memo_context"), + arkts.factory.createBinaryExpression( + arkts.factory.createIdentifier("__memo_id"), + arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + arkts.factory.createStringLiteral("key_id_main.ts") + ) + ] + )), + ...node.body.statements, + arkts.factory.createReturnStatement( + arkts.factory.createCallExpression( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("recache") + ) + ) + ), + ] + return arkts.factory.updateMethodDeclaration( + node, + undefined, + undefined, + arkts.factory.updateIdentifier( + node.name, + node.name.text.slice(ANNOTATION.length) + ), + undefined, + undefined, + [ + memoContextParam, + memoIdParam, + ...node.parameters + ], + undefined, + arkts.factory.updateBlock( + node.body, + bodyStatements + ) + ) +} + +export class MemoTransformer extends AbstractVisitor { + constructor( + // public tracer: Tracer, + // public sourceFile: api.SourceFile, + // public functionTable: FunctionTable, + // ctx: api.TransformationContext + ) { + // super(ctx) + super() + } + + visitor(beforeChildren: arkts.Node): arkts.Node { + const node: arkts.Node = this.visitEachChild(beforeChildren) + + if (isAnnotatedMethodDeclaration(node) && arkts.isMethodDeclaration(node)) { + return transformMethodDeclaration(node) + } else if (isAnnotatedCallExpression(node) && arkts.isCallExpression(node) && arkts.isIdentifier(node.expression)) { + return transformCallExpression(node) + } + + return node + } +} diff --git a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts index 971ed3decebc59190c295efbf46902c6c50a898d..caee5aa08a554ed5551eacd2a8d87622f9aef1ca 100644 --- a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts +++ b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts @@ -1,83 +1,23 @@ -import * as api from "api"; +import * as arkts from "../../src/arkts" +import { AbstractVisitor } from "./AbstractVisitor"; -export class PrintVisitor { +export class PrintVisitor extends AbstractVisitor { private result = "" - private depth = 0 private print(s: string) { - this.result += " ".repeat(4 * this.depth) + s + '\n' + this.result += " ".repeat(4 * this.indentation) + s + '\n' } - private visit(node: api.Node) { - this.depth += 1 - this.visitNode(node) - this.depth -= 1 + visitor(beforeChildren: arkts.Node): arkts.Node { + this.print(beforeChildren.constructor.name) + const node = this.visitEachChild(beforeChildren) + + return node } - private visitNode(node: api.Node) { - if (api.isSourceFile(node)) { - this.print(`SourceFile`) - node.statements.forEach((statement: api.Node) => this.visit(statement)) - return - } - if (api.isFunctionDeclaration(node)) { - this.print(`FunctionDeclaration`) - // this.visit(node.name!) - // this.visit(node.body!) - return - } - if (api.isIdentifier(node)) { - this.print(`Identifier ${node.text}`) - return - } - if (api.isBlock(node)) { - this.print(`Block`) - node.statements.forEach((statement: api.Node) => this.visit(statement)) - return - } - if (api.isCallExpression(node)) { - this.print(`CallExpression`) - this.visit(node.expression) - node.arguments.forEach((argument: api.Node) => this.visit(argument)) - return - } - if (api.isExpressionStatement(node)) { - this.print(`ExpressionStatement`) - this.visit(node.expression) - return - } - if (api.isStringLiteral(node)) { - this.print(`StringLiteral ${node.text}`) - return - } - if (api.isPropertyAccessExpression(node)) { - this.print(`PropertyAccessExpression`) - this.visit(node.expression) - this.visit(node.name) - return - } - if (api.isMethodDeclaration(node)) { - this.print(`MethodDeclaration`) - return - } - if (api.isClassDeclaration(node)) { - this.print(`ClassDeclaration`) - node.members.forEach((member: api.Node) => this.visit(member)) - return - } - if (api.isPropertyDeclaration(node)) { - this.print(`PropertyDeclaration`) - // node.members.forEach((member: api.Node) => this.visit(member)) - return - } - - this.print(`UnsupportedNode`) - } - - astToString(node: api.Node) { + astToString(node: arkts.Node): string { this.result = "" - this.depth = -1 - this.visit(node) + this.visitor(node) return this.result.trim() } -} \ No newline at end of file +} diff --git a/arkoala-arkts/libarkts/input/main.sts b/arkoala-arkts/libarkts/input/main.sts new file mode 100644 index 0000000000000000000000000000000000000000..de0a61a25f596b27b100962a24905454deae2859 --- /dev/null +++ b/arkoala-arkts/libarkts/input/main.sts @@ -0,0 +1,5 @@ +function Foo(builder: (instance: string) => string, arg1: string): void { + console.log(arg1 + builder("ABC")) +} + +_BuilderLambdaCall_Foo("> second_char_of_ABC: ").charAt(1) diff --git a/arkoala-arkts/libarkts/input/main.ts b/arkoala-arkts/libarkts/input/main.ts deleted file mode 100644 index e9c6decc7ff6a423d61ee57605118664f8d77e14..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/input/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -class A { - private foo() {} - goo() {} - - a: number = 1 -} diff --git a/arkoala-arkts/libarkts/native/.gitignore b/arkoala-arkts/libarkts/native/.gitignore index 10c4470cc39f130fd726d9563ec84afe35fa5384..8ef7ae46c2111ea5747c36b676f83055ac1f9206 100644 --- a/arkoala-arkts/libarkts/native/.gitignore +++ b/arkoala-arkts/libarkts/native/.gitignore @@ -1,2 +1,3 @@ prebuilt build-* +*.abc diff --git a/arkoala-arkts/libarkts/native/meson.build b/arkoala-arkts/libarkts/native/meson.build index 4be47c81ce5afa3d1bce842ad3e0eaf1ab0acac2..67ba731539b1eebfc71a10a4578d955e92f246a1 100644 --- a/arkoala-arkts/libarkts/native/meson.build +++ b/arkoala-arkts/libarkts/native/meson.build @@ -3,18 +3,13 @@ project('Es2panda interop', 'cpp', default_options: ['cpp_std=c++17', 'buildtype=debug'], ) -is_dummy = get_option('dummy') source_dir = meson.current_source_dir() interop_src = '../../../interop/src/cpp' es2panda_header = '../../../incremental/tools/panda/node_modules/@panda/sdk/ohos_arm64/include/tools/es2panda/public' es2panda_gen = '../../../incremental/tools/panda/node_modules/@panda/sdk/ohos_arm64/include/tools/es2panda/' is_msvc = meson.get_compiler('cpp').get_id() == 'msvc' -if is_dummy - implementation = './src/dummy_lib.cc' -else - implementation = './src/es2panda_lib.cc' -endif +implementation = './src/es2panda_lib.cc' os = target_machine.system() diff --git a/arkoala-arkts/libarkts/native/meson_options.txt b/arkoala-arkts/libarkts/native/meson_options.txt index 51966ed59cb036ff8d96159c7751c0f16a71331c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/arkoala-arkts/libarkts/native/meson_options.txt +++ b/arkoala-arkts/libarkts/native/meson_options.txt @@ -1,2 +0,0 @@ -option('dummy', type : 'boolean', value : 'false', - description : 'implementation') diff --git a/arkoala-arkts/libarkts/native/src/dummy_lib.cc b/arkoala-arkts/libarkts/native/src/dummy_lib.cc deleted file mode 100644 index f778c2a022c3cf923a91b7cc4fe743da1f3a4e00..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/native/src/dummy_lib.cc +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "es2panda_lib.h" -#include "common-interop.h" -#include "node.h" - -using std::string; - -KNativePointer impl_CreateConfig(KInt argc, KStringArray argv) { - return nullptr; -} -KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray) - -KNativePointer impl_CreateContextFromString(KNativePointer config, KStringPtr sourcePtr, KStringPtr filenamePtr) { - return nullptr; -} -KOALA_INTEROP_3(CreateContextFromString, KNativePointer, KNativePointer, KStringPtr, KStringPtr) - -KNativePointer impl_ProceedToState(KNativePointer context, KInt state) { - return nullptr; -} -KOALA_INTEROP_2(ProceedToState, KNativePointer, KNativePointer, KInt) - -KNativePointer impl_ContextProgram(KNativePointer context) { - return nullptr; -} -KOALA_INTEROP_1(ContextProgram, KNativePointer, KNativePointer) - -KNativePointer impl_ProgramAst(KNativePointer program) { - return new SourceFile({ - new FunctionDeclaration( - new Identifier("main"), - new Block({ - new ExpressionStatement( - new CallExpression( - new PropertyAccessExpression( - new Identifier("console"), - new Identifier("log") - ), - { - new StringLiteral("hello") - } - ) - ) - }) - ) - }); -} -KOALA_INTEROP_1(ProgramAst, KNativePointer, KNativePointer) - -KNativePointer impl_SourceFileGetChildren(KNativePointer sourceFilePtr) { - auto sourceFile = reinterpret_cast(sourceFilePtr); - return &sourceFile->children; -} -KOALA_INTEROP_1(SourceFileGetChildren, KNativePointer, KNativePointer) - -KNativePointer impl_BlockStatementStatements(KNativePointer blockPtr) { - auto sourceFile = reinterpret_cast(blockPtr); - return &sourceFile->statements; -} -KOALA_INTEROP_1(BlockStatementStatements, KNativePointer, KNativePointer) - -KNativePointer impl_FunctionDeclarationGetIdentifier(KNativePointer functionDeclarationPtr) { - auto functionDeclaration = reinterpret_cast(functionDeclarationPtr); - return functionDeclaration->identifier; -} -KOALA_INTEROP_1(FunctionDeclarationGetIdentifier, KNativePointer, KNativePointer); - -KNativePointer impl_FunctionDeclarationGetBlock(KNativePointer functionDeclarationPtr) { - auto functionDeclaration = reinterpret_cast(functionDeclarationPtr); - return functionDeclaration->block; -} -KOALA_INTEROP_1(FunctionDeclarationGetBlock, KNativePointer, KNativePointer); - -KNativePointer impl_ExpressionStatementGetCallExpression(KNativePointer expressionStatementPtr) { - auto expressionStatement = reinterpret_cast(expressionStatementPtr); - return expressionStatement->call; -} -KOALA_INTEROP_1(ExpressionStatementGetCallExpression, KNativePointer, KNativePointer); - -KNativePointer impl_CallExpressionGetPropertyAccessExpression(KNativePointer callExpressionPtr) { - auto call = reinterpret_cast(callExpressionPtr); - return call->propertyAccessExpression; -} -KOALA_INTEROP_1(CallExpressionGetPropertyAccessExpression, KNativePointer, KNativePointer); - -KNativePointer impl_CallExpressionGetArguments(KNativePointer callExpressionPtr) { - auto call = reinterpret_cast(callExpressionPtr); - return &call->arguments; -} -KOALA_INTEROP_1(CallExpressionGetArguments, KNativePointer, KNativePointer); - -KNativePointer impl_PropertyAccessExpressionGetExpression(KNativePointer propertyAccessExpressionPtr) { - auto propertyAccessExpression = reinterpret_cast(propertyAccessExpressionPtr); - return propertyAccessExpression->expression; -} -KOALA_INTEROP_1(PropertyAccessExpressionGetExpression, KNativePointer, KNativePointer); - -KNativePointer impl_PropertyAccessExpressionGetName(KNativePointer propertyAccessExpressionPtr) { - auto propertyAccessExpression = reinterpret_cast(propertyAccessExpressionPtr); - return propertyAccessExpression->name; -} -KOALA_INTEROP_1(PropertyAccessExpressionGetName, KNativePointer, KNativePointer); - -KInt impl_GetKind(KNativePointer nodePtr) { - auto node = reinterpret_cast(nodePtr); - return node->kind(); -} -KOALA_INTEROP_1(GetKind, KInt, KNativePointer) - -KNativePointer impl_IdentifierName(KNativePointer contextPtr, KNativePointer identifierPtr) { - auto identifier = reinterpret_cast(identifierPtr); - return new string(identifier->name); -} -KOALA_INTEROP_2(IdentifierName, KNativePointer, KNativePointer, KNativePointer) - -KNativePointer impl_StringLiteralString(KNativePointer contextPtr, KNativePointer stringLiteralPtr) { - auto stringLiteral = reinterpret_cast(stringLiteralPtr); - return new string(stringLiteral->text); -} -KOALA_INTEROP_2(StringLiteralString, KNativePointer, KNativePointer, KNativePointer) diff --git a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc index 9d7d8defd5cfdbf0d7a7d7fc89bf69493191b522..1809f9055c7f311b665e611c54b83356d132ec5a 100644 --- a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc +++ b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc @@ -58,7 +58,7 @@ es2panda_Impl *GetImpl() { return impl; } -es2panda_ContextState intToState(int state) { +es2panda_ContextState intToState(KInt state) { return es2panda_ContextState(state); } @@ -67,7 +67,6 @@ string getString(KStringPtr ptr) { } char* getStringCopy(KStringPtr ptr) { - // TODO: fix memory leak here return strdup(ptr.c_str()); } @@ -75,20 +74,33 @@ inline KUInt unpackUInt(const KByte* bytes) { return (bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24)); } -KNativePointer impl_CreateConfig(KInt argc, KStringArray argv) { - std::vector res(argc); - size_t offset = sizeof(KUInt); - const char** args = new const char*[argc]; - for (KInt i = 0; i < argc; ++i) { - auto s = argv + offset; - auto* str = reinterpret_cast(&s[sizeof(KUInt)]); - res[i] = std::string(str, unpackUInt(s)); - offset += res[i].size() + sizeof(KUInt); - args[i] = res[i].c_str(); +KInt impl_ContextState(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + + return static_cast(GetImpl()->ContextState(context)); +} +KOALA_INTEROP_1(ContextState, KInt, KNativePointer) + +KNativePointer impl_ContextErrorMessage(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + + return new string(GetImpl()->ContextErrorMessage(context)); +} +KOALA_INTEROP_1(ContextErrorMessage, KNativePointer, KNativePointer) + +KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) { + const std::size_t HEADER_LEN = 4; + + const char** argv = new const char*[argc]; + std::size_t position = HEADER_LEN; + std::size_t str_len; + for (std::size_t i = 0; i < argc; ++i) { + str_len = unpackUInt(argvPtr + position); + position += HEADER_LEN; + argv[i] = strdup(std::string(reinterpret_cast(argvPtr + position), str_len).c_str()); + position += str_len; } - auto result = GetImpl()->CreateConfig(argc, args); - delete [] args; - return result; + return GetImpl()->CreateConfig(argc, argv); } KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray) @@ -112,6 +124,26 @@ KNativePointer impl_ContextProgram(KNativePointer contextPtr) { } KOALA_INTEROP_1(ContextProgram, KNativePointer, KNativePointer) +KBoolean impl_CheckerStartChecker(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + return GetImpl()->CheckerStartChecker(context); +} +KOALA_INTEROP_1(CheckerStartChecker, KBoolean, KNativePointer) + +KNativePointer impl_VarBinderIdentifierAnalysis(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + GetImpl()->VarBinderIdentifierAnalysis(context); + return context; +} +KOALA_INTEROP_1(VarBinderIdentifierAnalysis, KNativePointer, KNativePointer) + +KNativePointer impl_VarBinderInitTopScope(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + GetImpl()->VarBinderInitTopScope(context); + return context; +} +KOALA_INTEROP_1(VarBinderInitTopScope, KNativePointer, KNativePointer) + KNativePointer impl_ProgramAst(KNativePointer programPtr) { auto program = reinterpret_cast(programPtr); return GetImpl()->ProgramAst(program); @@ -144,11 +176,20 @@ KNativePointer impl_CreateIdentifier2(KNativePointer contextPtr, KStringPtr name } KOALA_INTEROP_3(CreateIdentifier2, KNativePointer, KNativePointer, KStringPtr, KNativePointer) -KNativePointer impl_CreateETSPrimitiveType0(KNativePointer contextPtr, KInt type) { +KNativePointer impl_CreateETSPrimitiveType(KNativePointer contextPtr, KInt type) { auto context = reinterpret_cast(contextPtr); - return GetImpl()->CreateETSPrimitiveType0(context, static_cast(type)); + return GetImpl()->CreateETSPrimitiveType(context, static_cast(type)); } -KOALA_INTEROP_2(CreateETSPrimitiveType0, KNativePointer, KNativePointer, KInt) +KOALA_INTEROP_2(CreateETSPrimitiveType, KNativePointer, KNativePointer, KInt) + +KNativePointer impl_CreateETSFunctionTypeIr(KNativePointer contextPtr, KNativePointer signaturePtr, KInt funcFlagsT) { + auto context = reinterpret_cast(contextPtr); + auto signature = reinterpret_cast(signaturePtr); + auto funcFlags = Es2pandaScriptFunctionFlags(funcFlagsT); + + return GetImpl()->CreateETSFunctionTypeIr(context, signature, funcFlags); +} +KOALA_INTEROP_3(CreateETSFunctionTypeIr, KNativePointer, KNativePointer, KNativePointer, KInt) KNativePointer impl_CreateStringLiteral(KNativePointer contextPtr, KStringPtr stringPtr) { auto context = reinterpret_cast(contextPtr); @@ -170,6 +211,13 @@ KNativePointer impl_AstNodeDumpJsonConst(KNativePointer contextPtr, KNativePoint } KOALA_INTEROP_2(AstNodeDumpJsonConst, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_AstNodeDumpEtsSrcConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return new string(GetImpl()->AstNodeDumpEtsSrcConst(context, node)); +} +KOALA_INTEROP_2(AstNodeDumpEtsSrcConst, KNativePointer, KNativePointer, KNativePointer) + /* TODO: AstNodeKind should be provided by es2panda */ @@ -182,6 +230,16 @@ enum AstNodeKind { FunctionDeclaration = 6, ClassProperty = 7, TSTypeParameterDeclaration = 8, + ETSFunctionType = 9, + CallExpression = 10, + ExpressionStatement = 11, + MemberExpression = 12, + ArrowFunctionExpression = 13, + ReturnStatement = 14, + ETSParameterExpression = 15, + NumberLiteral = 16, + VariableDeclaration = 17, + ClassStaticBlock = 18, }; KInt impl_GetKind(KNativePointer nodePtr) { @@ -208,9 +266,39 @@ KInt impl_GetKind(KNativePointer nodePtr) { if (GetImpl()->IsClassProperty(node)) { return AstNodeKind::ClassProperty; } - if (GetImpl()->IsTSTypeParameterDeclaration) { + if (GetImpl()->IsTSTypeParameterDeclaration(node)) { return AstNodeKind::TSTypeParameterDeclaration; } + if (GetImpl()->IsETSFunctionType(node)) { + return AstNodeKind::ETSFunctionType; + } + if (GetImpl()->IsCallExpression(node)) { + return AstNodeKind::CallExpression; + } + if (GetImpl()->IsExpressionStatement(node)) { + return AstNodeKind::ExpressionStatement; + } + if (GetImpl()->IsMemberExpression(node)) { + return AstNodeKind::MemberExpression; + } + if (GetImpl()->IsArrowFunctionExpression(node)) { + return AstNodeKind::ArrowFunctionExpression; + } + if (GetImpl()->IsReturnStatement(node)) { + return AstNodeKind::ReturnStatement; + } + if (GetImpl()->IsETSParameterExpression(node)) { + return AstNodeKind::ETSParameterExpression; + } + if (GetImpl()->IsNumberLiteral(node)) { + return AstNodeKind::NumberLiteral; + } + if (GetImpl()->IsVariableDeclaration(node)) { + return AstNodeKind::VariableDeclaration; + } + if (GetImpl()->IsClassStaticBlock(node)) { + return AstNodeKind::ClassStaticBlock; + } return -1; } @@ -238,6 +326,16 @@ KNativePointer impl_BlockStatementStatements(KNativePointer contextPtr, KNativeP } KOALA_INTEROP_2(BlockStatementStatements, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_BlockStatementUpdateStatements(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointerArray statementListPtr, KInt statementListLen, KNativePointer returnTypeLenPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto statementList = reinterpret_cast(statementListPtr); + size_t n; + auto statements = GetImpl()->BlockStatementUpdateStatements(context, node, statementList, statementListLen, &n); + return new vector(statements, statements + n); +} +KOALA_INTEROP_5(BlockStatementUpdateStatements, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer) + KNativePointer impl_ClassDeclarationDefinition(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -277,83 +375,778 @@ KNativePointer impl_ScriptFunctionId(KNativePointer contextPtr, KNativePointer n } KOALA_INTEROP_2(ScriptFunctionId, KNativePointer, KNativePointer, KNativePointer) -// TODO: support body and return type -KNativePointer impl_CreateFunctionDeclaration(KNativePointer contextPtr, KStringPtr namePtr, KNativePointerArray paramsPtr, KInt paramsLen) { +KBoolean impl_ScriptFunctionDeclareConst(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); - auto name = getStringCopy(namePtr); - auto parameters = reinterpret_cast(paramsPtr); - - es2panda_AstNode* firstStatement = nullptr; - es2panda_AstNode* firstParam = nullptr; - auto function_body = GetImpl()->CreateBlockStatement0(context, &firstStatement, 0); - - auto return_type = nullptr; - - auto function_signature = GetImpl()->CreateFunctionSignature0(context, nullptr, parameters, paramsLen, return_type); - - auto script_function = GetImpl()->CreateScriptFunction0(context, function_body, function_signature, SCRIPT_FUNCTION_FLAGS_NONE, MODIFIER_FLAGS_NONE, false); - - GetImpl()->AstNodeSetParent(context, function_body, script_function); + auto node = reinterpret_cast(nodePtr); + return GetImpl()->ScriptFunctionDeclareConst(context, node); +} +KOALA_INTEROP_2(ScriptFunctionDeclareConst, KBoolean, KNativePointer, KNativePointer) - es2panda_AstNode* ident = GetImpl()->CreateIdentifier1(context, name); - GetImpl()->ScriptFunctionSetIdent(context, script_function, ident); +KNativePointer impl_CreateFunctionDeclaration(KNativePointer contextPtr, KNativePointer funcPtr, KBoolean isAnonK) { + auto context = reinterpret_cast(contextPtr); + auto func = reinterpret_cast(funcPtr); + auto isAnon = static_cast(isAnonK); - return GetImpl()->CreateFunctionDeclaration0(context, script_function, false); + return GetImpl()->CreateFunctionDeclaration(context, func, isAnon); } -KOALA_INTEROP_4(CreateFunctionDeclaration, KNativePointer, KNativePointer, KStringPtr, KNativePointerArray, KInt) +KOALA_INTEROP_3(CreateFunctionDeclaration, KNativePointer, KNativePointer, KNativePointer, KBoolean) -// TODO: support body and return type KNativePointer impl_UpdateFunctionDeclaration( KNativePointer contextPtr, KNativePointer nodePtr, - KStringPtr namePtr, - KNativePointerArray paramsPtr, - KInt paramsLen + KNativePointer funcPtr, + KBoolean isAnonK ) { auto context = reinterpret_cast(contextPtr); - auto name = getStringCopy(namePtr); - auto func_decl_node = reinterpret_cast(nodePtr); - auto script_func_node = GetImpl()->FunctionDeclarationFunction(context, func_decl_node); - auto parameters = reinterpret_cast(paramsPtr); - auto old_signature = GetImpl()->ScriptFunctionIrSignature(context, script_func_node); - auto new_signature = GetImpl()->CreateFunctionSignature0( - context, - GetImpl()->FunctionSignatureTypeParams(context, old_signature), - parameters, - paramsLen, - GetImpl()->FunctionSignatureReturnType(context, old_signature) - ); - GetImpl()->ScriptFunctionUpdateIrSignature(context, script_func_node, new_signature); - - es2panda_AstNode* ident = GetImpl()->CreateIdentifier1(context, name); - GetImpl()->ScriptFunctionSetIdent(context, script_func_node, ident); - return func_decl_node; -} -KOALA_INTEROP_5(UpdateFunctionDeclaration, KNativePointer, KNativePointer, KNativePointer, KStringPtr, KNativePointerArray, KInt) + auto node = reinterpret_cast(nodePtr); + auto func = reinterpret_cast(funcPtr); + auto isAnon = static_cast(isAnonK); + + return GetImpl()->UpdateFunctionDeclaration(context, node, func, isAnon); +} +KOALA_INTEROP_4(UpdateFunctionDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KBoolean) // TODO: add param initializer KNativePointer impl_CreateETSParameterExpression(KNativePointer contextPtr, KNativePointer identifierPtr) { auto context = reinterpret_cast(contextPtr); auto identifier = reinterpret_cast(identifierPtr); - return GetImpl()->CreateETSParameterExpression0(context, identifier, nullptr); + return GetImpl()->CreateETSParameterExpression(context, identifier, nullptr); } KOALA_INTEROP_2(CreateETSParameterExpression, KNativePointer, KNativePointer, KNativePointer) -KNativePointer impl_CreateETSTypeReference0(KNativePointer contextPtr, KNativePointer partPtr) { +KNativePointer impl_ETSParameterExpressionIdent(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ETSParameterExpressionIdent(context, node); +} +KOALA_INTEROP_2(ETSParameterExpressionIdent, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateETSTypeReference(KNativePointer contextPtr, KNativePointer partPtr) { auto context = reinterpret_cast(contextPtr); auto part = reinterpret_cast(partPtr); - return GetImpl()->CreateETSTypeReference0(context, part); + return GetImpl()->CreateETSTypeReference(context, part); +} +KOALA_INTEROP_2(CreateETSTypeReference, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateETSTypeReferencePart1(KNativePointer contextPtr, KNativePointer namePtr) { + auto context = reinterpret_cast(contextPtr); + auto name = reinterpret_cast(namePtr); + + return GetImpl()->CreateETSTypeReferencePart1(context, name); } -KOALA_INTEROP_2(CreateETSTypeReference0, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_2(CreateETSTypeReferencePart1, KNativePointer, KNativePointer, KNativePointer) -KNativePointer impl_CreateETSTypeReferencePart0(KNativePointer contextPtr, KNativePointer namePtr, KNativePointer typeParamsPtr, KNativePointer prevPtr) { +KNativePointer impl_CreateETSTypeReferencePart(KNativePointer contextPtr, KNativePointer namePtr, KNativePointer typeParamsPtr, KNativePointer prevPtr) { auto context = reinterpret_cast(contextPtr); auto name = reinterpret_cast(namePtr); auto typeParams = reinterpret_cast(typeParamsPtr); auto prev = reinterpret_cast(prevPtr); - return GetImpl()->CreateETSTypeReferencePart0(context, name, typeParams, prev); + return GetImpl()->CreateETSTypeReferencePart(context, name, typeParams, prev); +} +KOALA_INTEROP_4(CreateETSTypeReferencePart, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_UpdateBlockStatement(KNativePointer contextPtr, KNativePointer originalPtr, KNativePointerArray statementListPtr, KInt statementListLen) { + auto context = reinterpret_cast(contextPtr); + auto statementList = reinterpret_cast(statementListPtr); + auto original = reinterpret_cast(originalPtr); + + // tmp solution while waiting fix for UpdateBlockStatement + GetImpl()->BlockStatementSetStatements(context, original, statementList, static_cast(statementListLen)); + return original; +} +KOALA_INTEROP_4(UpdateBlockStatement, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_CreateReturnStatement1(KNativePointer contextPtr, KNativePointer argumentPtr) { + auto context = reinterpret_cast(contextPtr); + auto argument = reinterpret_cast(argumentPtr); + + return GetImpl()->CreateReturnStatement1(context, argument); +} +KOALA_INTEROP_2(CreateReturnStatement1, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ReturnStatementArgument(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ReturnStatementArgument(context, node); +} +KOALA_INTEROP_2(ReturnStatementArgument, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateIfStatement(KNativePointer contextPtr, KNativePointer testPtr, KNativePointer consequentPtr, KNativePointer alternatePtr) { + auto context = reinterpret_cast(contextPtr); + auto test = reinterpret_cast(testPtr); + auto consequent = reinterpret_cast(consequentPtr); + auto alternate = reinterpret_cast(alternatePtr); + + return GetImpl()->CreateIfStatement(context, test, consequent, alternate); +} +KOALA_INTEROP_4(CreateIfStatement, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateMemberExpression( + KNativePointer contextPtr, + KNativePointer objectPtr, + KNativePointer propertyPtr, + KInt kindT, + KBoolean computedT, + KBoolean optionalT +) { + auto context = reinterpret_cast(contextPtr); + auto object = reinterpret_cast(objectPtr); + auto property = reinterpret_cast(propertyPtr); + auto computed = static_cast(computedT); + auto optional = static_cast(optionalT); + auto kind = static_cast(kindT); + + return GetImpl()->CreateMemberExpression(context, object, property, kind, computed, optional); +} +KOALA_INTEROP_6(CreateMemberExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KInt, KBoolean, KBoolean) + +KNativePointer impl_UpdateMemberExpression( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointer objectPtr, + KNativePointer propertyPtr, + KInt kindT, + KBoolean computedT, + KBoolean optionalT +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto object = reinterpret_cast(objectPtr); + auto property = reinterpret_cast(propertyPtr); + auto computed = static_cast(computedT); + auto optional = static_cast(optionalT); + auto kind = static_cast(kindT); + + return GetImpl()->UpdateMemberExpression(context, node, object, property, kind, computed, optional); +} +KOALA_INTEROP_7(UpdateMemberExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KInt, KBoolean, KBoolean) + +KNativePointer impl_UpdateMethodDefinition( + KNativePointer contextPtr, + KNativePointer nodePtr, + KInt kindT, + KNativePointer keyPtr, + KNativePointer valuePtr, + KInt modifiersT, + KBoolean isComputedT +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto kind = static_cast(kindT); + auto key = reinterpret_cast(keyPtr); + auto value = reinterpret_cast(valuePtr); + auto modifiers = static_cast(modifiersT); + auto isComputed = static_cast(isComputedT); + + return GetImpl()->UpdateMethodDefinition(context, node, kind, key, value, modifiers, isComputed); +} +KOALA_INTEROP_7(UpdateMethodDefinition, KNativePointer, KNativePointer, KNativePointer, KInt, KNativePointer, KNativePointer, KInt, KBoolean) + +KNativePointer impl_MemberExpressionObject( + KNativePointer contextPtr, + KNativePointer nodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->MemberExpressionObject(context, node); +} +KOALA_INTEROP_2(MemberExpressionObject, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_MemberExpressionProperty( + KNativePointer contextPtr, + KNativePointer nodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->MemberExpressionProperty(context, node); +} +KOALA_INTEROP_2(MemberExpressionProperty, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateCallExpression( + KNativePointer contextPtr, + KNativePointer calleePtr, + KNativePointerArray argumentsPtr, + KInt argumentsLen, + KNativePointer typeParamsPtr, + KBoolean optionalT, + KBoolean trailingCommaT +) { + auto context = reinterpret_cast(contextPtr); + auto callee = reinterpret_cast(calleePtr); + auto arguments = reinterpret_cast(argumentsPtr); + auto typeParams = reinterpret_cast(typeParamsPtr); + auto optional = static_cast(optionalT); + auto trailingComma = static_cast(trailingCommaT); + + return GetImpl()->CreateCallExpression(context, callee, arguments, argumentsLen, typeParams, optional, trailingComma); +} +KOALA_INTEROP_7(CreateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean) + +KNativePointer impl_UpdateCallExpression( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointer calleePtr, + KNativePointerArray argumentsPtr, + KInt argumentsLen, + KNativePointer typeParamsPtr, + KBoolean optionalT, + KBoolean trailingCommaT +) { + auto node = reinterpret_cast(nodePtr); + auto context = reinterpret_cast(contextPtr); + auto callee = reinterpret_cast(calleePtr); + auto arguments = reinterpret_cast(argumentsPtr); + auto typeParams = reinterpret_cast(typeParamsPtr); + auto optional = static_cast(optionalT); + auto trailingComma = static_cast(trailingCommaT); + + return GetImpl()->UpdateCallExpression(context, node, callee, arguments, argumentsLen, typeParams, optional, trailingComma); +} +KOALA_INTEROP_8(UpdateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean) + +KNativePointer impl_CreateExpressionStatement(KNativePointer contextPtr, KNativePointer exprPtr) { + auto context = reinterpret_cast(contextPtr); + auto expr = reinterpret_cast(exprPtr); + + return GetImpl()->CreateExpressionStatement(context, expr); +} +KOALA_INTEROP_2(CreateExpressionStatement, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_UpdateExpressionStatement(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer exprPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto expr = reinterpret_cast(exprPtr); + + return GetImpl()->UpdateExpressionStatement(context, node, expr); +} +KOALA_INTEROP_3(UpdateExpressionStatement, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionBody(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionBody(context, node); +} +KOALA_INTEROP_2(ScriptFunctionBody, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateBinaryExpression(KNativePointer contextPtr, KNativePointer leftPtr, KNativePointer rightPtr, KInt tokenKind) { + auto context = reinterpret_cast(contextPtr); + auto left = reinterpret_cast(leftPtr); + auto right = reinterpret_cast(rightPtr); + + return GetImpl()->CreateBinaryExpression(context, left, right, Es2pandaTokenType(tokenKind)); +} +KOALA_INTEROP_4(CreateBinaryExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KInt) + +KNativePointer impl_CreateFunctionSignature( + KNativePointer contextPtr, + KNativePointer typeParamsPtr, + KNativePointerArray paramsPtr, + KInt paramsLen, + KNativePointer returnTypeAnnotationPtr +) { + auto context = reinterpret_cast(contextPtr); + auto typeParams = reinterpret_cast(typeParamsPtr); + auto params = reinterpret_cast(paramsPtr); + auto returnTypeAnnotation = reinterpret_cast(returnTypeAnnotationPtr); + + return GetImpl()->CreateFunctionSignature(context, typeParams, params, paramsLen, returnTypeAnnotation); +} +KOALA_INTEROP_5(CreateFunctionSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer) + +KNativePointer impl_CreateScriptFunction( + KNativePointer contextPtr, + KNativePointer databodyPtr, + KNativePointer datasignaturePtr, + KInt datafuncFlags, + KInt dataFlags, + KBoolean datadeclare +) { + auto context = reinterpret_cast(contextPtr); + auto databody = reinterpret_cast(databodyPtr); + auto datasignature = reinterpret_cast(datasignaturePtr); + + return GetImpl()->CreateScriptFunction(context, databody, datasignature, datafuncFlags, dataFlags, datadeclare); +} +KOALA_INTEROP_6(CreateScriptFunction, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KInt, KInt, KBoolean) + +KNativePointer impl_UpdateScriptFunction( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointer databodyPtr, + KNativePointer datasignaturePtr, + KInt datafuncFlags, + KInt dataFlags, + KBoolean datadeclare +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto databody = reinterpret_cast(databodyPtr); + auto datasignature = reinterpret_cast(datasignaturePtr); + + return GetImpl()->UpdateScriptFunction(context, node, databody, datasignature, datafuncFlags, dataFlags, datadeclare); +} +KOALA_INTEROP_7(UpdateScriptFunction, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KInt, KInt, KBoolean) + +KNativePointer impl_CreateBlockStatement( + KNativePointer contextPtr, + KNativePointerArray statementListPtr, + KInt statementListLen +) { + auto context = reinterpret_cast(contextPtr); + auto statementList = reinterpret_cast(statementListPtr); + + return GetImpl()->CreateBlockStatement(context, statementList, statementListLen); +} +KOALA_INTEROP_3(CreateBlockStatement, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +// TODO: rewrite everything here +es2panda_AstNode * __parentNode; +es2panda_Context * __context; + +static void changeParent(es2panda_AstNode *child) +{ + GetImpl()->AstNodeSetParent(__context, child, __parentNode); +} + +static void SetRightParent(es2panda_AstNode *node, void *arg) +{ + es2panda_Context *ctx = static_cast(arg); + __context = ctx; + __parentNode = node; + GetImpl()->AstNodeIterateConst(ctx, node, changeParent); +} + +KNativePointer impl_UpdateAllChilds(KNativePointer contextPtr, KNativePointer programPtr) { + auto context = reinterpret_cast(contextPtr); + auto program = reinterpret_cast(programPtr); + + GetImpl()->AstNodeForEach(program, SetRightParent, context); + + return program; +} +KOALA_INTEROP_2(UpdateAllChilds, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeUpdateChildren(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + // auto lambda = [node, impl, context](es2panda_AstNode *child){ impl->AstNodeSetParent(context, child, node); }; + // void(decltype(lambda)::*ptr)(es2panda_AstNode*)const = &decltype(lambda)::operator(); + + // impl->AstNodeIterateConst(context, node, [node, impl, context](es2panda_AstNode *child){ impl->AstNodeSetParent(context, child, node); }); + // GetImpl()->AstNodeIterateConst(context, node, &decltype(lambda)::operator()); + + __parentNode = node; + GetImpl()->AstNodeIterateConst(context, node, changeParent); + + return node; +} +KOALA_INTEROP_2(AstNodeUpdateChildren, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_MethodDefinitionFunction( + KNativePointer contextPtr, + KNativePointer nodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->MethodDefinitionFunction(context, node); +} +KOALA_INTEROP_2(MethodDefinitionFunction, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeSetParent( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer parentPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto parent = reinterpret_cast(parentPtr); + + GetImpl()->AstNodeSetParent(context, ast, parent); + return ast; +} +KOALA_INTEROP_3(AstNodeSetParent, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeClone( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer parentPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto parent = reinterpret_cast(parentPtr); + + return GetImpl()->AstNodeClone(context, ast, parent); +} +KOALA_INTEROP_3(AstNodeClone, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSetIdent( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer idPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto id = reinterpret_cast(idPtr); + + GetImpl()->ScriptFunctionSetIdent(context, ast, id); + return ast; +} +KOALA_INTEROP_3(ScriptFunctionSetIdent, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSetSignature( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer signaturePtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto signature = reinterpret_cast(signaturePtr); + + GetImpl()->ScriptFunctionSetSignature(context, ast, signature); + return ast; +} +KOALA_INTEROP_3(ScriptFunctionSetSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSetIrSignature( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer signaturePtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto signature = reinterpret_cast(signaturePtr); + + GetImpl()->ScriptFunctionSetIrSignature(context, ast, signature); + return ast; +} +KOALA_INTEROP_3(ScriptFunctionSetIrSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSetBody( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer bodyPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto body = reinterpret_cast(bodyPtr); + + GetImpl()->ScriptFunctionSetBody(context, ast, body); + return ast; +} +KOALA_INTEROP_3(ScriptFunctionSetBody, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSetScope( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer scopePtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto scope = reinterpret_cast(scopePtr); + + GetImpl()->ScriptFunctionSetScope(context, ast, scope); + return ast; +} +KOALA_INTEROP_3(ScriptFunctionSetScope, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionSignature(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionSignature(context, node); +} +KOALA_INTEROP_2(ScriptFunctionSignature, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionIrSignature(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionIrSignature(context, node); +} +KOALA_INTEROP_2(ScriptFunctionIrSignature, KNativePointer, KNativePointer, KNativePointer) + +KInt impl_ScriptFunctionFlagsConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionFlagsConst(context, node); +} +KOALA_INTEROP_2(ScriptFunctionFlagsConst, KInt, KNativePointer, KNativePointer) + +KInt impl_AstNodeModifiers(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->AstNodeModifiers(context, node); +} +KOALA_INTEROP_2(AstNodeModifiers, KInt, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeAddModifier(KNativePointer contextPtr, KNativePointer nodePtr, KInt flagsT) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto flags = static_cast(flagsT); + + GetImpl()->AstNodeAddModifier(context, node, flags); + return node; +} +KOALA_INTEROP_3(AstNodeAddModifier, KNativePointer, KNativePointer, KNativePointer, KInt) + +KNativePointer impl_AstNodeClearModifier(KNativePointer contextPtr, KNativePointer nodePtr, KInt flagsT) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto flags = static_cast(flagsT); + + GetImpl()->AstNodeClearModifier(context, node, flags); + return node; +} +KOALA_INTEROP_3(AstNodeClearModifier, KNativePointer, KNativePointer, KNativePointer, KInt) + +KNativePointer impl_FunctionSignatureTypeParams(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->FunctionSignatureTypeParams(context, node); +} +KOALA_INTEROP_2(FunctionSignatureTypeParams, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_FunctionSignatureReturnType(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->FunctionSignatureReturnType(context, node); +} +KOALA_INTEROP_2(FunctionSignatureReturnType, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_UpdateIdentifier1(KNativePointer contextPtr, KNativePointer nodePtr, KStringPtr namePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->UpdateIdentifier1(context, node, getStringCopy(namePtr)); +} +KOALA_INTEROP_3(UpdateIdentifier1, KNativePointer, KNativePointer, KNativePointer, KStringPtr) + +KNativePointer impl_UpdateIdentifier2(KNativePointer contextPtr, KNativePointer nodePtr, KStringPtr namePtr, KNativePointer typeAnnotationPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto typeAnnotation = reinterpret_cast(typeAnnotationPtr); + + return GetImpl()->UpdateIdentifier2(context, node, getStringCopy(namePtr), typeAnnotation); +} +KOALA_INTEROP_4(UpdateIdentifier2, KNativePointer, KNativePointer, KNativePointer, KStringPtr, KNativePointer) + +KNativePointer impl_IdentifierSetReference(KNativePointer contextPtr, KNativePointer nodePtr, KBoolean isReferenceK) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto isReference = static_cast(isReferenceK); + + GetImpl()->IdentifierSetReference(context, node, isReference); + return node; +} +KOALA_INTEROP_3(IdentifierSetReference, KNativePointer, KNativePointer, KNativePointer, KBoolean) + +KNativePointer impl_ScriptFunctionUpdateIrSignature(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer signaturePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto signature = reinterpret_cast(signaturePtr); + + return GetImpl()->ScriptFunctionUpdateIrSignature(context, node, signature); +} +KOALA_INTEROP_3(ScriptFunctionUpdateIrSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateFunctionExpression(KNativePointer contextPtr, KNativePointer funcPtr) { + auto context = reinterpret_cast(contextPtr); + auto func = reinterpret_cast(funcPtr); + + return GetImpl()->CreateFunctionExpression(context, func); +} +KOALA_INTEROP_2(CreateFunctionExpression, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateArrowFunctionExpression(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->CreateArrowFunctionExpression(context, node); +} +KOALA_INTEROP_2(CreateArrowFunctionExpression, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ArrowFunctionExpressionFunction(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ArrowFunctionExpressionFunction(context, node); +} +KOALA_INTEROP_2(ArrowFunctionExpressionFunction, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ArrowFunctionExpressionCreateTypeAnnotation(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ArrowFunctionExpressionCreateTypeAnnotation(context, node); +} +KOALA_INTEROP_2(ArrowFunctionExpressionCreateTypeAnnotation, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ExpressionStatementGetExpression(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ExpressionStatementGetExpression(context, node); +} +KOALA_INTEROP_2(ExpressionStatementGetExpression, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CallExpressionArguments(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer returnLen) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + std::size_t params_len = 0; + auto params = GetImpl()->CallExpressionArguments(context, node, ¶ms_len); + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(CallExpressionArguments, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CallExpressionCallee(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return GetImpl()->CallExpressionCallee(context, node); +} +KOALA_INTEROP_2(CallExpressionCallee, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeParent(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return GetImpl()->AstNodeParent(context, node); +} +KOALA_INTEROP_2(AstNodeParent, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeVariableConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->AstNodeVariableConst(context, node); +} +KOALA_INTEROP_2(AstNodeVariableConst, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_VariableDeclaration(KNativePointer contextPtr, KNativePointer variablePtr) { + auto context = reinterpret_cast(contextPtr); + auto variable = reinterpret_cast(variablePtr); + + return GetImpl()->VariableDeclaration(context, variable); +} +KOALA_INTEROP_2(VariableDeclaration, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_DeclNode(KNativePointer contextPtr, KNativePointer declPtr) { + auto context = reinterpret_cast(contextPtr); + auto decl = reinterpret_cast(declPtr); + + return GetImpl()->DeclNode(context, decl); +} +KOALA_INTEROP_2(DeclNode, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeScopeConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return GetImpl()->AstNodeScopeConst(context, node); +} +KOALA_INTEROP_2(AstNodeScopeConst, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScopeSetParent(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer parentPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto parent = reinterpret_cast(parentPtr); + GetImpl()->ScopeSetParent(context, node, parent); + return node; +} +KOALA_INTEROP_3(ScopeSetParent, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_BlockStatementSetStatements( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointerArray statementsPtr, + KInt statementsLen +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto statements = reinterpret_cast(statementsPtr); + + GetImpl()->BlockStatementSetStatements(context, node, statements, statementsLen); + return node; +} +KOALA_INTEROP_4(BlockStatementSetStatements, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_VarBinderSetProgram(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + + GetImpl()->VarBinderSetProgram(context); + return nullptr; +} +KOALA_INTEROP_1(VarBinderSetProgram, KNativePointer, KNativePointer) + +KNativePointer impl_VarBinderSetContext(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + + GetImpl()->VarBinderSetContext(context); + return nullptr; +} +KOALA_INTEROP_1(VarBinderSetContext, KNativePointer, KNativePointer) + +KNativePointer impl_UpdateClassDeclaration(KNativePointer contextPtr, KNativePointer originalPtr, KNativePointer defPtr) { + auto context = reinterpret_cast(contextPtr); + auto original = reinterpret_cast(originalPtr); + auto def = reinterpret_cast(defPtr); + + return GetImpl()->UpdateClassDeclaration(context, original, def); +} +KOALA_INTEROP_3(UpdateClassDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ClassDefinitionLanguageConst( + KNativePointer contextPtr, + KNativePointer nodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ClassDefinitionLanguageConst(context, node); +} +KOALA_INTEROP_2(ClassDefinitionLanguageConst, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ClassDefinitionIdent( + KNativePointer contextPtr, + KNativePointer nodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ClassDefinitionIdent(context, node); +} +KOALA_INTEROP_2(ClassDefinitionIdent, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_UpdateClassDefinition1( + KNativePointer contextPtr, + KNativePointer originalPtr, + KNativePointer identPtr, + KNativePointerArray bodyPtr, + KInt bodyLenT, + KInt modifiersT, + KInt flagsT, + KNativePointer langT +) { + auto context = reinterpret_cast(contextPtr); + auto original = reinterpret_cast(originalPtr); + auto ident = reinterpret_cast(identPtr); + auto body = reinterpret_cast(bodyPtr); + auto bodyLen = static_cast(bodyLenT); + auto modifiers = Es2pandaClassDefinitionModifiers(modifiersT); + auto flags = Es2pandaModifierFlags(flagsT); + auto lang = reinterpret_cast(langT); + + return GetImpl()->UpdateClassDefinition1(context, original, ident, body, bodyLen, modifiers, flags, lang); } -KOALA_INTEROP_4(CreateETSTypeReferencePart0, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_8(UpdateClassDefinition1, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KInt, KInt, KNativePointer) diff --git a/arkoala-arkts/libarkts/native/src/playground.cc b/arkoala-arkts/libarkts/native/src/playground.cc index c811085df7500e4b34890bdf3f1746c128d394a9..4ce6caaf3a56ca6c1c8a0335497171813c6334c4 100644 --- a/arkoala-arkts/libarkts/native/src/playground.cc +++ b/arkoala-arkts/libarkts/native/src/playground.cc @@ -26,14 +26,78 @@ es2panda_Impl *GetImpl() { static char* source = ""; int main() { - size_t argc = 4; - const char* argv[] = { "_", "--arktsconfig", "../arktsconfig.json", "../input/main.ts" }; - auto config = GetImpl()->CreateConfig(argc, argv); - auto context = GetImpl()->CreateContextFromString(config, source, "../input/main.ts"); + const char* args[] = { + // command with which the program is invoked (ignored) + "", + "--arktsconfig", + // path to config + "../arktsconfig.json", + // path to source + "../input/main.sts" + }; - GetImpl()->ProceedToState(context, ES2PANDA_STATE_PARSED); - auto program = GetImpl()->ContextProgram(context); - auto peer = GetImpl()->ProgramAst(program); + auto config = GetImpl()->CreateConfig(4, args); + auto context = GetImpl()->CreateContextFromString(config, source, args[3]); // playground + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_PARSED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO PARSE ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO PARSE SUCCESS" << std::endl; + } + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_SCOPE_INITED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO SCOPE INITED ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO SCOPE INITED SUCCESS" << std::endl; + } + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_CHECKED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO CHECKED ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO CHECKED SUCCESS" << std::endl; + } + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_LOWERED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO LOWERED ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO LOWERED SUCCESS" << std::endl; + } + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_ASM_GENERATED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO ASM ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO ASM SUCCESS" << std::endl; + } + + GetImpl()->ProceedToState(context, ES2PANDA_STATE_BIN_GENERATED); + if(GetImpl()->ContextState(context) == ES2PANDA_STATE_ERROR) + { + std::cout << "PROCEED TO BIN ERROR" << std::endl; + std::cout << GetImpl()->ContextErrorMessage(context) << std::endl; + } + else { + std::cout << "PROCEED TO BIN SUCCESS" << std::endl; + } } diff --git a/arkoala-arkts/libarkts/package.json b/arkoala-arkts/libarkts/package.json index efd37bb0c9d82a9005a9103b756b57c686445285..f86c2863530392a9710630c3dce5dcf21f7d32f2 100644 --- a/arkoala-arkts/libarkts/package.json +++ b/arkoala-arkts/libarkts/package.json @@ -18,21 +18,18 @@ }, "scripts": { "clean": "rimraf build node_modules && npm run clean:native && npm run clean:compatible", - "clean:native": "rimraf native/build_dummy native/build_es2panda", + "clean:native": "rimraf native/build_es2panda", "clean:compatible": "rimraf compatible/build compatible/build_typescript compatible/build_arkts", "compile:koala:interop": "cd ../../interop && npm run compile", - "compile:native:dummy": "cd native && meson setup -D dummy=true build_dummy && cd build_dummy && meson compile", - "compile:dummy": "npm run compile:koala:interop && npm run compile:native:dummy", - "test:dummy": "npm run compile:dummy && backend=dummy TS_NODE_PROJECT=./test/tsconfig.json npx mocha -r tsconfig-paths/register --config .mocha-dummy.json", - "compile:native": "cd native && meson setup -D dummy=false build_es2panda && cd build_es2panda && meson compile", + "compile:native": "cd native && meson setup build_es2panda && cd build_es2panda && meson compile", "compile": "npm run compile:koala:interop && npm run compile:native", "test": "npm run compile && backend=es2panda TS_NODE_PROJECT=./test/tsconfig.json mocha -r tsconfig-paths/register --config .mocha.json", "compatible": "cd compatible && npx webpack --config arkts.webpack.config.js", "webpack": "npm run compile && npm run compatible && npx webpack --config es2panda.webpack.config.js", "run:dev": "npm run run && backend=es2panda node build/api/es2panda.js", - "test:all": "npm run test:dummy && npm run test", - "run": "npm run webpack && node build/api/es2panda.js --file ./input/main.ts --arktsconfig ./arktsconfig.json", + "run": "npm run webpack && node build/api/es2panda.js --file ./input/main.sts --arktsconfig ./arktsconfig.json", "run:typescript": "npm run compatible && cd input && memo-tsc -p ./tsconfig.json", - "run:debug": "npm run compile:native && cd native && ./build_es2panda/playground_exec" + "run:debug": "npm run compile:native && cd native && ./build_es2panda/playground_exec", + "run:abc": "/home/huawei/arkts/arkcompiler/runtime_core/static_core/build/bin/ark --load-runtimes=ets --boot-panda-files=/home/huawei/arkts/arkcompiler/runtime_core/static_core/build/plugins/ets/etsstdlib.abc ./native/main.abc ETSGLOBAL::main" } } diff --git a/arkoala-arkts/libarkts/src/NativeModule.ts b/arkoala-arkts/libarkts/src/NativeModule.ts index 861d93b33789bd3a57ab45aea91384c07b00b0dc..2f27eb1603fbef3c5c0d37758b5e1113f848de3f 100644 --- a/arkoala-arkts/libarkts/src/NativeModule.ts +++ b/arkoala-arkts/libarkts/src/NativeModule.ts @@ -16,12 +16,20 @@ import { KBoolean, KInt, KNativePointer } from "@koalaui/interop" import * as path from "path" +export type KNativePointerArray = BigUint64Array + export interface NativeModule { + _ContextState(context: KNativePointer): KInt + _ContextErrorMessage(context: KNativePointer): KNativePointer + _CreateConfig(argc: number, argv: string[]): KNativePointer _CreateContextFromString(config: KNativePointer, source: String, filename: String): KNativePointer _ProceedToState(context: KNativePointer, state: number): void _ContextProgram(context: KNativePointer): KNativePointer _ProgramAst(program: KNativePointer): KNativePointer + _CheckerStartChecker(context: KNativePointer): KBoolean + _VarBinderIdentifierAnalysis(context: KNativePointer): void + _VarBinderInitTopScope(context: KNativePointer): void _StringLength(ptr: KNativePointer): KInt _StringData(ptr: KNativePointer, buffer: KNativePointer, length: KInt): void @@ -34,9 +42,9 @@ export interface NativeModule { _BlockGetStatements(node: KNativePointer): KNativePointer _FunctionDeclarationGetIdentifier(node: KNativePointer): KNativePointer _FunctionDeclarationGetBlock(node: KNativePointer): KNativePointer - _ExpressionStatementGetCallExpression(node: KNativePointer): KNativePointer - _CallExpressionGetPropertyAccessExpression(node: KNativePointer): KNativePointer - _CallExpressionGetArguments(node: KNativePointer): KNativePointer + _ExpressionStatementGetExpression(context: KNativePointer, node: KNativePointer): KNativePointer + _CallExpressionArguments(context: KNativePointer, node: KNativePointer, returnLen: KNativePointer): KNativePointer + _CallExpressionCallee(context: KNativePointer, node: KNativePointer): KNativePointer _IdentifierGetText(node: KNativePointer): KNativePointer _PropertyAccessExpressionGetExpression(node: KNativePointer): KNativePointer _PropertyAccessExpressionGetName(node: KNativePointer): KNativePointer @@ -45,16 +53,68 @@ export interface NativeModule { _ScriptFunctionSignature(context: KNativePointer, node: KNativePointer): KNativePointer _ScriptFunctionParams(context: KNativePointer, node: KNativePointer): KNativePointer _ScriptFunctionId(context: KNativePointer, node: KNativePointer): KNativePointer - _CreateIdentifier1(context: KNativePointer, name: string): KNativePointer - _CreateIdentifier2(context: KNativePointer, name: string, type_annotation: KNativePointer): KNativePointer - _CreateFunctionDeclaration(context: KNativePointer, name: string, parameters: BigUint64Array, paramsLen: KInt): KNativePointer - _UpdateFunctionDeclaration(context: KNativePointer, node: KNativePointer, name: string, parameters: BigUint64Array, paramsLen: KInt): KNativePointer + _ScriptFunctionBody(context: KNativePointer, node: KNativePointer): KNativePointer + _ScriptFunctionSetIdent(context: KNativePointer, ast: KNativePointer, id: KNativePointer): KNativePointer + _ScriptFunctionIrSignature(context: KNativePointer, ast: KNativePointer): KNativePointer + _ScriptFunctionUpdateIrSignature(context: KNativePointer, ast: KNativePointer, signature: KNativePointer): KNativePointer + _ScriptFunctionSetSignature(context: KNativePointer, ast: KNativePointer, signature: KNativePointer): KNativePointer + _ScriptFunctionSetIrSignature(context: KNativePointer, ast: KNativePointer, signature: KNativePointer): KNativePointer + _ScriptFunctionSetBody(context: KNativePointer, ast: KNativePointer, body: KNativePointer): KNativePointer + _ScriptFunctionSetScope(context: KNativePointer, ast: KNativePointer, scope: KNativePointer): KNativePointer + _ScriptFunctionDeclareConst(context: KNativePointer, node: KNativePointer): KBoolean + _ScriptFunctionFlagsConst(context: KNativePointer, node: KNativePointer): KInt + _UpdateBlockStatement(context: KNativePointer, original: KNativePointer, statementList: KNativePointerArray, statementListLen: KInt): KNativePointer + _BlockStatementSetScope(context: KNativePointer, node: KNativePointer, scope: KNativePointerArray): void + _CreateIdentifier1(context: KNativePointer, name: String): KNativePointer + _CreateIdentifier2(context: KNativePointer, name: String, type_annotation: KNativePointer): KNativePointer + _IdentifierSetReference(context: KNativePointer, node: KNativePointer, isRef: KBoolean): void + _CreateFunctionDeclaration(context: KNativePointer, func: KNativePointer, isAnon: KBoolean): KNativePointer + _UpdateFunctionDeclaration(context: KNativePointer, node: KNativePointer, func: KNativePointer, isAnon: KBoolean): KNativePointer + _CreateReturnStatement1(context: KNativePointer, argument: KNativePointer): KNativePointer + _ReturnStatementArgument(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateIfStatement(context: KNativePointer, test: KNativePointer, consequent: KNativePointer, alternate: KNativePointer): KNativePointer + _CreateBinaryExpression(context: KNativePointer, left: KNativePointer, right: KNativePointer, operatorType: KInt): KNativePointer + + _CreateFunctionSignature(context: KNativePointer, typeParams: KNativePointer, params: KNativePointerArray, paramsLen: KInt, returnTypeAnnotation: KNativePointer): KNativePointer + _CreateScriptFunction(context: KNativePointer, databody: KNativePointer, datasignature: KNativePointer, datafuncFlags: KInt, dataflags: KInt, datadeclare: KBoolean): KNativePointer + _UpdateScriptFunction(context: KNativePointer, original: KNativePointer, databody: KNativePointer, datasignature: KNativePointer, datafuncFlags: KInt, dataflags: KInt, datadeclare: KBoolean): KNativePointer + _CreateBlockStatement(context: KNativePointer, statementList: KNativePointerArray, statementListLen: KInt): KNativePointer + _AstNodeScopeConst(context: KNativePointer, ast: KNativePointer): KNativePointer + _AstNodeParent(context: KNativePointer, ast: KNativePointer): KNativePointer + _AstNodeSetParent(context: KNativePointer, ast: KNativePointer, parent: KNativePointer): KNativePointer + _AstNodeClone(context: KNativePointer, ast: KNativePointer, parent: KNativePointer): KNativePointer + _AstNodeModifiers(context: KNativePointer, ast: KNativePointer): KInt + _AstNodeAddModifier(context: KNativePointer, ast: KNativePointer, flags: KInt): void + _AstNodeClearModifier(context: KNativePointer, ast: KNativePointer, flags: KInt): void + _AstNodeVariableConst(context: KNativePointer, ast: KNativePointer): KNativePointer + _FunctionSignatureTypeParams(context: KNativePointer, ast: KNativePointer): KNativePointer + _FunctionSignatureReturnType(context: KNativePointer, ast: KNativePointer): KNativePointer + _UpdateIdentifier1(context: KNativePointer, ast: KNativePointer, name: string): KNativePointer + _UpdateIdentifier2(context: KNativePointer, ast: KNativePointer, name: string, typeAnnotation: KNativePointer): KNativePointer + _UpdateMethodDefinition(context: KNativePointer, node: KNativePointer, kind: KInt, key: KNativePointer, value: KNativePointer, modifiers: KInt, isComputed: KBoolean): KNativePointer + _MethodDefinitionFunction(context: KNativePointer, node: KNativePointer): KNativePointer + + _CreateMemberExpression(context: KNativePointer, object: KNativePointer, property: KNativePointer, kind: KInt, computed: KBoolean, optional: KBoolean): KNativePointer + _UpdateMemberExpression(context: KNativePointer, node: KNativePointer, object: KNativePointer, property: KNativePointer, kind: KInt, computed: KBoolean, optional: KBoolean): KNativePointer + _MemberExpressionObject(context: KNativePointer, node: KNativePointer): KNativePointer + _MemberExpressionProperty(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateCallExpression(context: KNativePointer, callee: KNativePointer, args: KNativePointerArray, argsLen: KInt, typeParams: KNativePointer, optional: KBoolean, trailingComma: KBoolean): KNativePointer + _UpdateCallExpression(node: KNativePointer, context: KNativePointer, callee: KNativePointer, args: KNativePointerArray, argsLen: KInt, typeParams: KNativePointer, optional: KBoolean, trailingComma: KBoolean): KNativePointer + _CreateArrowFunctionExpression(context: KNativePointer, node: KNativePointer): KNativePointer + _ArrowFunctionExpressionFunction(context: KNativePointer, node: KNativePointer): KNativePointer + _ArrowFunctionExpressionCreateTypeAnnotation(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateFunctionExpression(context: KNativePointer, node: KNativePointer): KNativePointer + + _CreateExpressionStatement(context: KNativePointer, expr: KNativePointer): KNativePointer + _UpdateExpressionStatement(context: KNativePointer, node: KNativePointer, expr: KNativePointer): KNativePointer _CreateETSParameterExpression(context: KNativePointer, identifier: KNativePointer): KNativePointer - _CreateETSPrimitiveType0(context: KNativePointer, type: KInt): KNativePointer - _CreateETSTypeReference0(context: KNativePointer, part: KNativePointer): KNativePointer - _CreateETSTypeReferencePart0(context: KNativePointer, name: KNativePointer, typeParams: KNativePointer, prev: KNativePointer): KNativePointer + _CreateETSPrimitiveType(context: KNativePointer, type: KInt): KNativePointer + _CreateETSTypeReference(context: KNativePointer, part: KNativePointer): KNativePointer + _CreateETSTypeReferencePart(context: KNativePointer, name: KNativePointer, typeParams: KNativePointer, prev: KNativePointer): KNativePointer + _CreateETSTypeReferencePart1(context: KNativePointer, name: KNativePointer): KNativePointer _IsIdentifier(node: KNativePointer): KBoolean _IdentifierName(context: KNativePointer, node: KNativePointer): KNativePointer + _ETSParameterExpressionIdent(context: KNativePointer, node: KNativePointer): KNativePointer _CreateStringLiteral(context: KNativePointer, string: string): KNativePointer _StringLiteralString(context: KNativePointer, node: KNativePointer): KNativePointer @@ -62,11 +122,28 @@ export interface NativeModule { _GetKind(node: KNativePointer): KInt _BlockStatementStatements(context: KNativePointer, node: KNativePointer): KNativePointer + _BlockStatementSetStatements(context: KNativePointer, node: KNativePointer, statements: KNativePointerArray, statementsLen: KInt): void + _BlockStatementUpdateStatements(context: KNativePointer, original: KNativePointer, statementList: KNativePointerArray, statementListLen: KInt, returnType: KNativePointer): KNativePointer _ClassDeclarationDefinition(context: KNativePointer, node: KNativePointer): KNativePointer _ClassDefinitionBody(context: KNativePointer, node: KNativePointer): KNativePointer + _ClassDefinitionLanguageConst(context: KNativePointer, node: KNativePointer): KNativePointer + _ClassDefinitionIdent(context: KNativePointer, node: KNativePointer): KNativePointer + _UpdateClassDeclaration(context: KNativePointer, original: KNativePointer, def: KNativePointer): KNativePointer + _UpdateClassDefinition1(context: KNativePointer, original: KNativePointer, ident: KNativePointer, body: KNativePointerArray, bodyLen: KInt, modifiers: KInt, flags: KInt, lang: KNativePointer): KNativePointer + _CreateETSFunctionTypeIr(context: KNativePointer, signature: KNativePointer, funcFlags: KInt): KNativePointer _IsProgram(context: KNativePointer, node: KNativePointer): KBoolean _AstNodeDumpJsonConst(context: KNativePointer, node: KNativePointer): KNativePointer + _AstNodeDumpEtsSrcConst(context: KNativePointer, node: KNativePointer): KNativePointer + _AstNodeUpdateChildren(context: KNativePointer, node: KNativePointer): void + + _VarBinderSetProgram(context: KNativePointer): void + _VarBinderSetContext(context: KNativePointer): void + + _VariableDeclaration(context: KNativePointer, variable: KNativePointer): KNativePointer + _DeclNode(context: KNativePointer, decl: KNativePointer): KNativePointer + + _ScopeSetParent(context: KNativePointer, ast: KNativePointer, scope: KNativePointer): void } const backend = process.env.backend ?? 'es2panda' diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts new file mode 100644 index 0000000000000000000000000000000000000000..6ed1cd0647dd1d75112c87e1a934dcac02176bad --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ts from "@koalaui/ets-tsc" +import { nativeModule } from "../../NativeModule" +import { Access, KNativePointer, withPtrArray, withString } from "@koalaui/interop" +import * as util from "../utilities" +import { + // util types: + Global, + NULLPTR, + NULLPTR_ARRAY, + + // ts types: + Node, + Identifier, + StringLiteral, + FunctionDeclaration, + Block, + KeywordTypeNode, + PropertyAccessExpression, + ParameterDeclaration, + ReturnStatement, + IfStatement, + ExpressionStatement, + CallExpression, + ArrowFunction, + TypeReferenceNode, + BinaryExpression, + BinaryOperatorToken, + ClassDeclaration, + FunctionTypeNode, + TypeNode, + Expression, + Statement, + SourceFile, + ClassElement, + + // ets types: + ETSPrimitiveType, + Es2pandaPrimitiveType, + MethodDeclaration, +} from "../types" + +export interface NodeFactory { + createIdentifier(name: string, typeAnnotation?: Node): Identifier; + updateIdentifier(node: Identifier, name: string, typeAnnotation?: TypeNode): Identifier; + createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; + createFunctionDeclaration( + modifiers: undefined, + asteriskToken: undefined, + name: Identifier, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block | undefined + ): FunctionDeclaration; + updateFunctionDeclaration( + node: FunctionDeclaration, + modifiers: undefined, + asteriskToken: undefined, + name: Identifier, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block | undefined + ): FunctionDeclaration; + createParameterDeclaration( + modifiers: undefined, + dotDotDotToken: undefined, + name: Identifier, + questionToken?: undefined, + type?: TypeNode, + initializer?: undefined + ): ParameterDeclaration; + createEtsPrimitiveType(type: Es2pandaPrimitiveType): ETSPrimitiveType; + createTypeReferenceNode(identifier: Identifier, typeArguments?: undefined): TypeReferenceNode; + createKeywordTypeNode(TKind: ts.KeywordTypeSyntaxKind): KeywordTypeNode; + createBlock(statements: Statement[], multiline?: boolean): Block; + updateBlock(node: Block, statements: Statement[], multiline?: boolean): Block; + createExpressionStatement(expression: Expression): ExpressionStatement; + updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + createReturnStatement(expression: Expression): ReturnStatement; + createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression; + updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + createCallExpression( + expression: Expression, + typeArguments?: undefined, + argumentsArray?: readonly Expression[] | undefined + ): CallExpression; + updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments?: undefined, + argumentsArray?: readonly Expression[] | undefined + ): CallExpression; + createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: undefined): IfStatement; + createToken(token: ts.TokenSyntaxKind): BinaryOperatorToken; + createBinaryExpression(left: Expression, operator: BinaryOperatorToken, right: Expression): BinaryExpression; + createArrowFunction( + modifiers: undefined, + typeParameters: undefined, + parameters: ParameterDeclaration[], + type: undefined, + equalsGreaterThanToken: undefined, + body: Block + ): ArrowFunction; + updateSourceFile(node: SourceFile, statements: readonly Statement[]): SourceFile; + updateClassDeclaration( + node: ClassDeclaration, + modifiers: undefined, + name: Identifier | undefined, + typeParameters: undefined, + heritageClauses: undefined, + members: readonly ClassElement[] + ): ClassDeclaration; + createFunctionTypeNode( + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode + ): FunctionTypeNode; + updateMethodDeclaration( + node: MethodDeclaration, + modifiers: undefined, // TODO: support (now default public, static) + asteriskToken: undefined, + name: Identifier, + questionToken: undefined, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block + ): MethodDeclaration; +} + +// TODO: add flags and base in the future +export function createNodeFactory(): NodeFactory { + const factory: NodeFactory = { + createIdentifier, + updateIdentifier, + createStringLiteral, + createFunctionDeclaration, + updateFunctionDeclaration, + createParameterDeclaration, + createEtsPrimitiveType, + createTypeReferenceNode, + createKeywordTypeNode, + createBlock, + updateBlock, + createExpressionStatement, + updateExpressionStatement, + createReturnStatement, + createPropertyAccessExpression, + updatePropertyAccessExpression, + createCallExpression, + updateCallExpression, + createIfStatement, + createToken, + createBinaryExpression, + createArrowFunction, + updateSourceFile, + updateClassDeclaration, + createFunctionTypeNode, + updateMethodDeclaration, + } + + return factory + + // @api + function createIdentifier(name: string, typeAnnotation?: Node): Identifier { + const peer = withString(name, (name: string) => { + if (typeAnnotation !== undefined) { + return nativeModule._CreateIdentifier2(Global.context, name, util.getPeer(typeAnnotation)) + } + return nativeModule._CreateIdentifier1(Global.context, name) + }) + if (typeAnnotation !== undefined) { + util.setParent(typeAnnotation.peer, peer) + } + + return new Identifier(peer) + } + + // @api + function updateIdentifier(node: Identifier, name: string, typeAnnotation?: TypeNode): Identifier { + const peer = + (typeAnnotation === undefined) + ? + nativeModule._UpdateIdentifier1(Global.context, util.getPeer(node), name) + : + nativeModule._UpdateIdentifier2(Global.context, util.getPeer(node), name, util.getPeer(typeAnnotation)) + + if (typeAnnotation !== undefined) { + util.setParent(typeAnnotation.peer, peer) + } + util.setModifierFlags(peer, util.getModifierFlags(node.peer)) + + return new Identifier(peer) + } + + // @api + function createStringLiteral(s: string): StringLiteral { + const peer = withString(s, (s: string) => { + return nativeModule._CreateStringLiteral(Global.context, s) + }) + + return new StringLiteral(peer) + } + + // tsc: createFunctionDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + // @api + function createFunctionDeclaration( + modifiers: undefined, + asteriskToken: undefined, + name: Identifier, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block | undefined + ): FunctionDeclaration { + const params = new BigUint64Array(parameters.map(node => BigInt(util.getPeer(node)))) + + const peer = withString(name.text, (_name: string) => { + return withPtrArray(params, Access.READWRITE, (_params: BigUint64Array) => { + const _paramsLen = params.length + const _context = Global.context + const _body = body ? util.getPeer(body) : NULLPTR + + const _signature = nativeModule._CreateFunctionSignature( + _context, + NULLPTR, + _params, + _paramsLen, + NULLPTR + ) + + const _scriptFunc = nativeModule._CreateScriptFunction( + _context, + _body, + _signature, + // TODO: fix flag params + 0, + 0, + false + ) + if (_body !== NULLPTR) { + nativeModule._AstNodeSetParent(_context, _body, _scriptFunc) + } + + const _ident = nativeModule._CreateIdentifier1(_context, _name) + nativeModule._ScriptFunctionSetIdent(_context, _scriptFunc, _ident) + nativeModule._AstNodeSetParent(Global.context, _ident, _scriptFunc) + + const _newFuncDecl = + nativeModule._CreateFunctionDeclaration( + _context, + _scriptFunc, + false + ) + nativeModule._AstNodeSetParent(Global.context, _scriptFunc, _newFuncDecl) + + return _newFuncDecl + }) + }) + + return new FunctionDeclaration(peer) + } + + // @api + function updateFunctionDeclaration( + node: FunctionDeclaration, + modifiers: undefined, + asteriskToken: undefined, + name: Identifier, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block | undefined + ): FunctionDeclaration { + const peer = withString(name.text, (_name: string) => { + return withPtrArray( + new BigUint64Array(parameters.map(node => BigInt(node.peer))), + Access.READWRITE, + (_parameters: BigUint64Array) => { + const _context = Global.context + + const _oldFuncDecl = node.peer + const _oldScriptFunc = nativeModule._FunctionDeclarationFunction( + _context, + _oldFuncDecl + ) + const _oldSignature = nativeModule._ScriptFunctionIrSignature( + _context, + _oldScriptFunc + ) + // TODO: use this flags + // const _oldFlags = nativeModule._ScriptFunctionFlagsConst(_context, _newScriptFunc) + + const _body = body ? body.peer : NULLPTR + const _signature = nativeModule._CreateFunctionSignature( + _context, + nativeModule._FunctionSignatureTypeParams(_context, _oldSignature), + _parameters, + _parameters.length, + nativeModule._FunctionSignatureReturnType(_context, _oldSignature) + ) + const _scriptFunc = nativeModule._UpdateScriptFunction( + _context, + _oldScriptFunc, + _body, + _signature, + 0, + 0, + false + ) + parameters.forEach(function (parameter: ParameterDeclaration) { + util.setParent(parameter.peer, _scriptFunc) + }) + if (_body !== NULLPTR) { + util.setParent(_body, _scriptFunc) + } + + const _ident = nativeModule._UpdateIdentifier1( + _context, + nativeModule._ScriptFunctionId(_context, _oldScriptFunc), + _name + ) + nativeModule._ScriptFunctionSetIdent(Global.context, _scriptFunc, _ident) + + const _funcDecl = + nativeModule._UpdateFunctionDeclaration( + _context, + _oldFuncDecl, + _scriptFunc, + false + ) + util.setParent(_scriptFunc, _funcDecl) + + util.setModifierFlags(_scriptFunc, util.getModifierFlags(_oldScriptFunc)) + util.setModifierFlags(_funcDecl, util.getModifierFlags(_oldFuncDecl)) + + return _funcDecl + }) + }) + + return new FunctionDeclaration(peer) + } + + // tsc: createParameterDeclaration(modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; + // @api + function createParameterDeclaration( + modifiers: undefined, + dotDotDotToken: undefined, + name: Identifier, + questionToken?: undefined, + type?: TypeNode, + initializer?: undefined + ): ParameterDeclaration { + const peer = nativeModule._CreateETSParameterExpression( + Global.context, + (type === undefined) + ? + util.getPeer(name) + : + util.getPeer(updateIdentifier( + name, + name.text, + type + )) + ) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(name), peer) + if (type !== undefined) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(type), peer) + } + + return new ParameterDeclaration(peer) + } + + // TODO: maybe remove from api + // @api + function createEtsPrimitiveType(type: Es2pandaPrimitiveType) { + const peer = nativeModule._CreateETSPrimitiveType(Global.context, type) + + return new ETSPrimitiveType(peer) + } + + // tsc: createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; + // @api + function createTypeReferenceNode(identifier: Identifier, typeArguments?: undefined): TypeReferenceNode { + const typeRefPart = nativeModule._CreateETSTypeReferencePart(Global.context, util.getPeer(identifier), NULLPTR, NULLPTR) + const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) + nativeModule._AstNodeSetParent(Global.context, typeRefPart, peer) + + return new TypeReferenceNode(peer) + } + + function createKeywordTypeNodeFromString(keyword: string): KeywordTypeNode { + const identifier: KNativePointer = withString(keyword, (name: string) => { + return nativeModule._CreateIdentifier1(Global.context, name) + }) + nativeModule._IdentifierSetReference(Global.context, identifier, true) + const typeRefPart = nativeModule._CreateETSTypeReferencePart1(Global.context, identifier) + nativeModule._AstNodeSetParent(Global.context, identifier, typeRefPart) + const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) + nativeModule._AstNodeSetParent(Global.context, typeRefPart, peer); + + return new KeywordTypeNode(peer) + } + + function createKeywordTypeNodeFromKind(kind: number): KeywordTypeNode { + return new KeywordTypeNode(nativeModule._CreateETSPrimitiveType(Global.context, kind)) + } + + // @api + function createKeywordTypeNode(TKind: ts.KeywordTypeSyntaxKind): KeywordTypeNode { + const keywords = new Map([ + [ts.SyntaxKind.NumberKeyword, createKeywordTypeNodeFromString("number")], + [ts.SyntaxKind.StringKeyword, createKeywordTypeNodeFromString("string")], + [ts.SyntaxKind.AnyKeyword, createKeywordTypeNodeFromString("any")], + [ts.SyntaxKind.VoidKeyword, createKeywordTypeNodeFromKind(8)], + ]) + + return keywords.get(TKind) ?? util.throwError('unsupported keyword') + } + + // @api + function createBlock(statements: Statement[], multiline?: boolean): Block { + const statementList = new BigUint64Array(statements.map(node => BigInt(util.getPeer(node)))) + + const peer = withPtrArray(statementList, Access.READWRITE, (statementList: BigUint64Array) => { + return nativeModule._CreateBlockStatement(Global.context, statementList, statementList.length) + }) + statements.forEach(function (statement: Statement) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(statement), peer) + }) + + return new Block(peer) + } + + // @api + function updateBlock(node: Block, statements: Statement[], multiline?: boolean): Block { + const statementList = new BigUint64Array(statements.map(node => BigInt(util.getPeer(node)))) + + const peer = withPtrArray(statementList, Access.READWRITE, (statementList: BigUint64Array) => { + return nativeModule._UpdateBlockStatement(Global.context, util.getPeer(node), statementList, statementList.length) + }) + statements.forEach(function (statement: Statement) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(statement), peer) + }) + + return new Block(peer) + } + + // @api + function createExpressionStatement(expression: Expression): ExpressionStatement { + const peer = nativeModule._CreateExpressionStatement(Global.context, util.getPeer(expression)) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + + return new ExpressionStatement(peer) + } + + // @api + function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement { + const peer = nativeModule._UpdateExpressionStatement(Global.context, util.getPeer(node), util.getPeer(expression)) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + + return new ExpressionStatement(peer) + } + + // @api + function createReturnStatement(expression: Expression): ReturnStatement { + const peer = nativeModule._CreateReturnStatement1(Global.context, util.getPeer(expression)) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + + return new ReturnStatement(peer) + } + + // tsc: createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; + // @api + function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression { + const peer = nativeModule._CreateMemberExpression(Global.context, util.getPeer(expression), util.getPeer(name), 2, false, false) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(name), peer) + + return new PropertyAccessExpression(peer) + } + + // @api + function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression { + const peer = nativeModule._UpdateMemberExpression(Global.context, util.getPeer(node), util.getPeer(expression), util.getPeer(name), 2, false, false) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(name), peer) + + return new PropertyAccessExpression(peer) + } + + // tsc: createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; + // @api + function createCallExpression( + expression: Expression, + typeArguments?: undefined, + argumentsArray?: readonly Expression[] | undefined + ): CallExpression { + const _arguments: readonly Expression[] = argumentsArray ? argumentsArray : [] + + const peer = withPtrArray( + new BigUint64Array(_arguments.map(node => BigInt(util.getPeer(node)))), + Access.READWRITE, + (args: BigUint64Array) => { + return nativeModule._CreateCallExpression( + Global.context, + util.getPeer(expression), + args, + args.length, + NULLPTR, + false, + false + ) + }) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + _arguments.forEach(function (argument: Expression) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(argument), peer) + }) + + return new CallExpression(peer) + } + + // tsc: updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; + // @api + function updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments?: undefined, + argumentsArray?: readonly Expression[] | undefined + ): CallExpression { + const _arguments: readonly Expression[] = argumentsArray ? argumentsArray : [] + + const peer = withPtrArray( + new BigUint64Array(_arguments.map(node => BigInt(util.getPeer(node)))), + Access.READWRITE, + (args: BigUint64Array) => { + return nativeModule._UpdateCallExpression( + Global.context, + node.peer, + expression.peer, + args, + args.length, + NULLPTR, + false, + false + ) + }) + util.setParent(expression.peer, peer) + _arguments.forEach(function (argument: Expression) { + util.setParent(argument.peer, peer) + }) + util.setModifierFlags(peer, util.getModifierFlags(node.peer)) + + return new CallExpression(peer) + } + + // tsc: createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; + // @api + function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: undefined): IfStatement { + const peer = nativeModule._CreateIfStatement(Global.context, util.getPeer(expression), util.getPeer(thenStatement), NULLPTR) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(expression), peer) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(thenStatement), peer) + + return new IfStatement(peer) + } + + // returns only BinaryOperatorToken temporary + // tsc: createToken(token: SyntaxKind._): _; + // @api + function createToken(token: ts.TokenSyntaxKind): BinaryOperatorToken { + return new BinaryOperatorToken(token) + } + + // tsc: createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; + // @api + function createBinaryExpression(left: Expression, operator: BinaryOperatorToken, right: Expression): BinaryExpression { + const peer = nativeModule._CreateBinaryExpression(Global.context, util.getPeer(left), util.getPeer(right), (operator as BinaryOperatorToken).token) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(left), peer) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(right), peer) + + return new BinaryExpression(peer) + } + + // tsc: createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + // @api + function createArrowFunction( + modifiers: undefined, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + equalsGreaterThanToken: undefined, + body: Block + ) { + const params = new BigUint64Array(parameters.map(node => BigInt(node.peer))) + + const peer = withPtrArray(params, Access.READWRITE, (_params: BigUint64Array) => { + const _context = Global.context + const _body = body.peer + + const _signature = nativeModule._CreateFunctionSignature( + _context, + NULLPTR, + _params, + _params.length, + NULLPTR + ) + + const _scriptFunc = nativeModule._CreateScriptFunction( + _context, + _body, + _signature, + // TODO: fix flag params + 4, + 0, + false + ) + if (_body !== NULLPTR) { + util.setParent(_body, _scriptFunc) + } + parameters.forEach(function (parameter: ParameterDeclaration) { + util.setParent(parameter.peer, _scriptFunc) + }) + + const _newArrowFunc = nativeModule._CreateArrowFunctionExpression( + _context, + _scriptFunc + ) + util.setParent(_scriptFunc, _newArrowFunc) + + return _newArrowFunc + }) + + return new ArrowFunction(peer) + } + + // @api + function updateSourceFile(node: SourceFile, statements: readonly Statement[]): SourceFile { + const statementList = new BigUint64Array(statements.map(node => BigInt(util.getPeer(node)))) + + withPtrArray(statementList, Access.READWRITE, (statementList: BigUint64Array) => { + nativeModule._BlockStatementSetStatements(Global.context, util.getPeer(node), statementList, statementList.length) + }) + statements.forEach(function (statement: Statement) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(statement), util.getPeer(node)) + }) + + return node + } + + // tsc: updateClassDeclaration( + // node: ClassDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // name: Identifier | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // heritageClauses: readonly HeritageClause[] | undefined, + // members: readonly ClassElement[] + // ): ClassDeclaration; + // @api + function updateClassDeclaration( + node: ClassDeclaration, + modifiers: undefined, + name: Identifier | undefined, + typeParameters: undefined, + heritageClauses: undefined, + members: readonly ClassElement[] + ) { + // TODO: support undefined name and other params + const _members = new BigUint64Array(members.map(node => BigInt(util.getPeer(node)))) + + const peer = withPtrArray(_members, Access.READWRITE, (_members: BigUint64Array) => { + const _context = Global.context + + const _classDefinition = nativeModule._ClassDeclarationDefinition( + _context, + util.getPeer(node) + ) + + const _lang = nativeModule._ClassDefinitionLanguageConst( + _context, + _classDefinition + ) + + const _newClassDefinition = nativeModule._UpdateClassDefinition1( + _context, + _classDefinition, + util.getPeer(name!), + _members, + _members.length, + 0, + 0, + _lang + ) + nativeModule._AstNodeSetParent(Global.context, util.getPeer(name!), _newClassDefinition) + members.forEach(function (member: ClassElement) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(member), _newClassDefinition) + }) + + return nativeModule._UpdateClassDeclaration( + _context, + util.getPeer(node), + _newClassDefinition + ) + }) + + return new ClassDeclaration(peer) + } + + // tsc: createFunctionTypeNode( + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // parameters: readonly ParameterDeclaration[], + // type: TypeNode + // ): FunctionTypeNode; + // @api + function createFunctionTypeNode( + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode + ): FunctionTypeNode { + const _parameters = new BigUint64Array(parameters.map(node => BigInt(util.getPeer(node)))) + + const _signature = withPtrArray(_parameters, Access.READWRITE, (_parameters: BigUint64Array) => { + return nativeModule._CreateFunctionSignature( + Global.context, + NULLPTR, + _parameters, + _parameters.length, + util.getPeer(type) + ) + }) + + const peer = nativeModule._CreateETSFunctionTypeIr( + Global.context, + _signature, + 0 + ) + // TODO: not sure about it, maybe parent should be signature somehow + parameters.forEach(function (parameter: ParameterDeclaration) { + nativeModule._AstNodeSetParent(Global.context, util.getPeer(parameter), peer) + }) + + return new FunctionTypeNode(peer) + } + + // @api + // tsc: updateMethodDeclaration( + // node: MethodDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // asteriskToken: AsteriskToken | undefined, + // name: PropertyName, + // questionToken: QuestionToken | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // parameters: readonly ParameterDeclaration[], + // type: TypeNode | undefined, + // body: Block | undefined + // ): MethodDeclaration; + function updateMethodDeclaration( + node: MethodDeclaration, + modifiers: undefined, // TODO: support (now default public, static) + asteriskToken: undefined, + name: Identifier, + questionToken: undefined, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + body: Block + ): MethodDeclaration { + const peer = withPtrArray( + new BigUint64Array(parameters.map(node => BigInt(node.peer))), + Access.READWRITE, + (_parameters: BigUint64Array) => { + const _context = Global.context + + const _signature = nativeModule._CreateFunctionSignature( + _context, + NULLPTR, + _parameters, + _parameters.length, + NULLPTR + ) + const _scriptFunc = nativeModule._CreateScriptFunction( + _context, + body.peer, + _signature, + // TODO: fix flag params + 0, + 0, + false + ) + nativeModule._ScriptFunctionSetIdent(Global.context, _scriptFunc, name.peer) + util.updateChildren(_scriptFunc) + + const _funcExpr = nativeModule._CreateFunctionExpression( + Global.context, + _scriptFunc + ) + util.updateChildren(_funcExpr) + + const _methodDefinition = nativeModule._UpdateMethodDefinition( + Global.context, + node.peer, + 2, + name.peer, + _funcExpr, + 5, + false + ) + util.updateChildren(_methodDefinition) + + return _methodDefinition + }) + return new MethodDeclaration(peer) + } +} + +export const factory: NodeFactory = createNodeFactory(); diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeImpls.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeImpls.ts deleted file mode 100644 index 2b5eccbb35bbe40c891a555035d80ba3b9489f4b..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/src/arkts/factory/nodeImpls.ts +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as api from "../index" -import { Access, fromPtrArray, KNativePointer, withPtrArray, withString, withStringArray, withStringResult } from "@koalaui/interop" -import { nativeModule } from "../../NativeModule" -import "../../node/Platform" -import { NativePtrDecoder } from "../../node/Platform" -import { throwError } from "../util" - -export enum ContextState { - ES2PANDA_STATE_NEW = 0, - ES2PANDA_STATE_PARSED = 1, - ES2PANDA_STATE_CHECKED = 2, - ES2PANDA_STATE_LOWERED = 3, - ES2PANDA_STATE_ASM_GENERATED = 4, - ES2PANDA_STATE_BIN_GENERATED = 5, - - ES2PANDA_STATE_ERROR = 6, -} - -export class Global { - private static _config?: KNativePointer - - public static set config(config: KNativePointer) { - if (Global._config !== undefined) { - throw new Error('Global.config already initialized') - } - Global._config = config - } - - public static get config(): KNativePointer { - return Global._config ?? throwError('Global.config not initialized') - } - - public static isInitializedConfig(): boolean { - return (Global._config !== undefined) - } - - private static _context?: KNativePointer - - public static set context(context: KNativePointer) { - // if (Global._context !== undefined) { - // throw new Error('Global.context already initialized') - // } - Global._context = context - } - - public static get context(): KNativePointer { - return Global._context ?? throwError('Global.context not initialized') - } - - public static isInitializedContext(): boolean { - return (Global._context !== undefined) - } -} - -const DECODER = new NativePtrDecoder() - -export function createConfig(input: string[]): KNativePointer { - const tail = input.slice(1) - return withStringArray(tail, (stringArray: string[]) => { - return nativeModule._CreateConfig(tail.length, stringArray) - }) -} - -export function createContextFromString(config: KNativePointer, source: string, filename: string): KNativePointer { - return withString(source, (srcPtr: string) => { - return withString(filename, (filenamePtr: string) => { - return nativeModule._CreateContextFromString(config, srcPtr, filenamePtr) - }) - }) -} - -export function proceedToState(state: ContextState): void { - nativeModule._ProceedToState(Global.context, state) -} - -export function contextProgram(): KNativePointer { - return nativeModule._ContextProgram(Global.context) -} - -export function programAst(program: KNativePointer) { // TODO: return type - const nativePtr: KNativePointer = nativeModule._ProgramAst(program) - return nativePtr -} - -function todo(): any { - throw new Error("Not yet implemented") -} - -/** TODO batch this */ -function unpack(arrayPtr: KNativePointer): ReadonlyArray { - const array = DECODER.decode(arrayPtr) - - return fromPtrArray(array, (peer: KNativePointer) => { - return makeView(peer) - }) -} - -abstract class NodeImpl implements api.Node { - peer: KNativePointer - - protected constructor(peer: KNativePointer) { - this.peer = peer - } - - getSourceFile(): api.SourceFile { throw new Error("Method not implemented.") } - getChildCount(sourceFile?: api.SourceFile | undefined): number { throw new Error("Method not implemented.") } - getChildAt(index: number, sourceFile?: api.SourceFile | undefined): api.Node { throw new Error("Method not implemented.") } - getChildren(sourceFile?: api.SourceFile | undefined): api.Node[] { throw new Error("Method not implemented.") } - getStart(sourceFile?: api.SourceFile | undefined, includeJsDocComment?: boolean | undefined): number { throw new Error("Method not implemented.") } - getFullStart(): number { throw new Error("Method not implemented.") } - getEnd(): number { throw new Error("Method not implemented.") } - getWidth(sourceFile?: api.SourceFileLike | undefined): number { throw new Error("Method not implemented.") } - getFullWidth(): number { throw new Error("Method not implemented.") } - getLeadingTriviaWidth(sourceFile?: api.SourceFile | undefined): number { throw new Error("Method not implemented.") } - getFullText(sourceFile?: api.SourceFile | undefined): string { throw new Error("Method not implemented.") } - getText(sourceFile?: api.SourceFile | undefined): string { throw new Error("Method not implemented.") } - getFirstToken(sourceFile?: api.SourceFile | undefined): api.Node | undefined { throw new Error("Method not implemented.") } - getLastToken(sourceFile?: api.SourceFile | undefined): api.Node | undefined { throw new Error("Method not implemented.") } - forEachChild(cbNode: (node: api.Node) => T | undefined, cbNodeArray?: ((nodes: api.NodeArray) => T | undefined) | undefined): T | undefined { throw new Error("Method not implemented.") } - - // TODO: support minimal interface - get flags(): api.NodeFlags { return todo() } - get parent(): api.Node { return todo() } - get pos(): number { return todo() } - get end(): number { return todo() } - abstract kind: api.SyntaxKind -} - -class FunctionDeclarationImpl extends NodeImpl implements api.FunctionDeclaration { - constructor(peer: KNativePointer) { - super(peer) - } - - private get _scriptFunction() { - return nativeModule._FunctionDeclarationFunction(Global.context, this.peer) - } - - get name(): api.Identifier { - return makeView(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as api.Identifier - } - - get body() { - return makeView(nativeModule._FunctionDeclarationGetBlock(this.peer)) as api.Block - } - - get parameters(): api.NodeArray { - const params = nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction) - return unpack(params) as api.NodeArray - } - - // TODO: support minimal interface - _functionLikeDeclarationBrand: any - _declarationBrand: any - _statementBrand: any - kind: api.SyntaxKind.FunctionDeclaration = api.SyntaxKind.FunctionDeclaration -} - -class IdentifierImpl extends NodeImpl implements api.Identifier { - constructor(peer: KNativePointer) { - super(peer) - } - - get text(): string { - return withStringResult(nativeModule._IdentifierName(Global.context, this.peer)) ?? throwError(`Couldn't get _IdentifierName`) - } - - // TODO: support minimal interface - get escapedText(): api.__String { return todo() } - _primaryExpressionBrand: any - _memberExpressionBrand: any - _leftHandSideExpressionBrand: any - _updateExpressionBrand: any - _unaryExpressionBrand: any - _expressionBrand: any - _declarationBrand: any - kind: api.SyntaxKind.Identifier = api.SyntaxKind.Identifier -} - -class BlockImpl extends NodeImpl implements api.Block { - constructor(peer: KNativePointer) { - super(peer) - } - - private _statements?: api.NodeArray - get statements(): api.NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = unpack(statementsPtr) as api.NodeArray - } - return this._statements - } - - // TODO: support minimal interface - _statementBrand: any - kind: api.SyntaxKind.Block = api.SyntaxKind.Block -} - -class SourceFileImpl extends NodeImpl implements api.SourceFile { - constructor(peer: KNativePointer) { - super(peer) - } - - private _statements?: api.NodeArray - get statements(): api.NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = unpack(statementsPtr) as api.NodeArray - } - return this._statements - } - - moduleName: string | undefined - getLineAndCharacterOfPosition(pos: number): api.LineAndCharacter { throw new Error("Method not implemented.") } - getLineEndOfPosition(pos: number): number { throw new Error("Method not implemented.") } - getLineStarts(): readonly number[] { throw new Error("Method not implemented.") } - getPositionOfLineAndCharacter(line: number, character: number): number { throw new Error("Method not implemented.") } - update(newText: string, textChangeRange: api.TextChangeRange): api.SourceFile { throw new Error("Method not implemented.") } - - // TODO: support minimal interface - get endOfFileToken(): api.Token { return todo() } - get fileName(): string { return todo() } - get text() { return todo() } - get amdDependencies(): readonly api.AmdDependency[] { return todo() } - get referencedFiles(): readonly api.FileReference[] { return todo() } - get typeReferenceDirectives(): readonly api.FileReference[] { return todo() } - get libReferenceDirectives(): readonly api.FileReference[] { return todo() } - get languageVariant(): api.LanguageVariant { return todo() } - get isDeclarationFile(): boolean { return todo() } - get hasNoDefaultLib(): boolean { return todo() } - get languageVersion(): api.ScriptTarget { return todo() } - _declarationBrand: any - kind: api.SyntaxKind.SourceFile = api.SyntaxKind.SourceFile -} - -class ExpressionStatementImpl extends NodeImpl implements api.ExpressionStatement { - constructor(peer: KNativePointer) { - super(peer) - } - - get expression(): api.Expression { - return makeView(nativeModule._ExpressionStatementGetCallExpression(this.peer)) as api.Expression - } - - // TODO: support minimal interface - _statementBrand: any - kind: api.SyntaxKind.ExpressionStatement = api.SyntaxKind.ExpressionStatement -} - -class CallExpressionImpl extends NodeImpl implements api.CallExpression { - constructor(peer: KNativePointer) { - super(peer) - } - - get expression(): api.LeftHandSideExpression { - return makeView(nativeModule._CallExpressionGetPropertyAccessExpression(this.peer)) as api.PropertyAccessExpression - } - - private _arguments?: api.NodeArray - get arguments(): api.NodeArray { - if (this._arguments === undefined) { - const argumentsPtr = nativeModule._CallExpressionGetArguments(this.peer) - this._arguments = unpack(argumentsPtr) as api.NodeArray - } - return this._arguments - } - - // TODO: support minimal interface - _leftHandSideExpressionBrand: any - _updateExpressionBrand: any - _unaryExpressionBrand: any - _expressionBrand: any - _declarationBrand: any - kind: api.SyntaxKind.CallExpression = api.SyntaxKind.CallExpression -} - -class PropertyAccessExpressionImpl extends NodeImpl implements api.PropertyAccessExpression { - constructor(peer: KNativePointer) { - super(peer) - } - - get name() { - return makeView(nativeModule._PropertyAccessExpressionGetName(this.peer)) as api.Identifier - } - - get expression() { - return makeView(nativeModule._PropertyAccessExpressionGetExpression(this.peer)) as api.Identifier - } - - // TODO: support minimal interface - _memberExpressionBrand: any - _leftHandSideExpressionBrand: any - _updateExpressionBrand: any - _unaryExpressionBrand: any - _expressionBrand: any - _declarationBrand: any - kind: api.SyntaxKind.PropertyAccessExpression = api.SyntaxKind.PropertyAccessExpression -} - -class StringLiteralImpl extends NodeImpl implements api.StringLiteral { - constructor(peer: KNativePointer) { - super(peer) - } - - get text(): string { - return withStringResult(nativeModule._StringLiteralString(Global.context, this.peer)) ?? throwError(`Couldn't get _StringLiteralString`) - } - - // TODO: support minimal interface - _literalExpressionBrand: any - _primaryExpressionBrand: any - _memberExpressionBrand: any - _leftHandSideExpressionBrand: any - _updateExpressionBrand: any - _unaryExpressionBrand: any - _expressionBrand: any - _declarationBrand: any - kind: api.SyntaxKind.StringLiteral = api.SyntaxKind.StringLiteral -} - -class ClassDeclarationImpl extends NodeImpl implements api.ClassDeclaration { - constructor(peer: KNativePointer) { - super(nativeModule._ClassDeclarationDefinition(Global.context, peer)) - } - - private _members?: api.NodeArray - get members(): api.NodeArray { - if (this._members === undefined) { - const membersPtr = nativeModule._ClassDefinitionBody(Global.context, this.peer) - this._members = unpack(membersPtr) as api.NodeArray - } - return this._members - } - - // TODO: support minimal interface - _declarationBrand: any - _statementBrand: any - kind: api.SyntaxKind.ClassDeclaration = api.SyntaxKind.ClassDeclaration; -} - -class MethodDeclarationImpl extends NodeImpl implements api.MethodDeclaration { - constructor(peer: KNativePointer) { - super(peer) - } - - // TODO: support minimal interface - get parent(): api.ClassLikeDeclaration | api.ObjectLiteralExpression { return todo() } - get name(): api.PropertyName { return todo() } - get parameters(): api.NodeArray { return todo() } - _functionLikeDeclarationBrand: any - _classElementBrand: any - _objectLiteralBrand: any - _declarationBrand: any - kind: api.SyntaxKind.MethodDeclaration = api.SyntaxKind.MethodDeclaration; -} - -class PropertyDeclarationImpl extends NodeImpl implements api.PropertyDeclaration { - constructor(peer: KNativePointer) { - super(peer) - } - - // TODO: support minimal interface - get parent(): api.ClassLikeDeclaration { return todo() } - get name(): api.PropertyName { return todo() } - _classElementBrand: any - _declarationBrand: any - kind: api.SyntaxKind.PropertyDeclaration = api.SyntaxKind.PropertyDeclaration; -} - -class ParameterDeclarationImpl extends NodeImpl implements api.ParameterDeclaration { - constructor(peer: KNativePointer) { - super(peer) - } - - // TODO: support minimal interface - get parent(): api.SignatureDeclaration { return todo() } - get name(): api.BindingName { return todo() } - _declarationBrand: any - kind: api.SyntaxKind.Parameter = api.SyntaxKind.Parameter; -} - -class ETSPrimitiveTypeImpl extends NodeImpl implements api.Node { - constructor(peer: KNativePointer) { - super(peer) - } - - kind: api.SyntaxKind.Unknown = api.SyntaxKind.Unknown; -} - -class KeywordTypeNodeImpl extends NodeImpl implements api.KeywordTypeNode { - constructor(peer: KNativePointer) { - super(peer) - } - - // TODO: support minimal interface - _typeNodeBrand: any - kind: api.KeywordTypeSyntaxKind = api.SyntaxKind.UnknownKeyword -} - -class TypeReferenceNodeImpl extends NodeImpl implements api.TypeReferenceNode { - constructor(peer: KNativePointer) { - super(peer) - } - - // TODO: support minimal interface - _typeNodeBrand: any - kind: api.SyntaxKind.TypeReference = api.SyntaxKind.TypeReference - typeName: any -} - -class UnsupportedNode extends NodeImpl implements api.Node { - constructor(peer: KNativePointer) { - super(peer) - } - - kind: api.SyntaxKind = -1 -} - -enum es2pandaKind { - Identifier = 1, - StringLiteral = 2, - Block = 3, - MethodDeclaration = 4, - ClassDeclaration = 5, - FunctionDeclaration = 6, - PropertyDeclaration = 7, - Parameter = 8, - - UnsupportedNode = -1, -} - -const kinds = new Map([ - [es2pandaKind.Identifier, api.SyntaxKind.Identifier], - [es2pandaKind.StringLiteral, api.SyntaxKind.StringLiteral], - [es2pandaKind.Block, api.SyntaxKind.Block], - [es2pandaKind.MethodDeclaration, api.SyntaxKind.MethodDeclaration], - [es2pandaKind.ClassDeclaration, api.SyntaxKind.ClassDeclaration], - [es2pandaKind.FunctionDeclaration, api.SyntaxKind.FunctionDeclaration], - [es2pandaKind.PropertyDeclaration, api.SyntaxKind.PropertyDeclaration], - [es2pandaKind.Parameter, api.SyntaxKind.Parameter], -]) - -export function makeView(peer: KNativePointer): api.Node { - const es2pandaKind = nativeModule._GetKind(peer) - if (nativeModule._IsProgram(Global.context, peer)) { - return new SourceFileImpl(peer) - } - - const kind: api.SyntaxKind | undefined = kinds.get(es2pandaKind) - - if (!kind) { - return new UnsupportedNode(peer) - } - - if (kind == api.SyntaxKind.Identifier) return new IdentifierImpl(peer) - if (kind == api.SyntaxKind.StringLiteral) return new StringLiteralImpl(peer) - if (kind == api.SyntaxKind.Block) return new BlockImpl(peer) - if (kind == api.SyntaxKind.MethodDeclaration) return new MethodDeclarationImpl(peer) - if (kind == api.SyntaxKind.ClassDeclaration) return new ClassDeclarationImpl(peer) - if (kind == api.SyntaxKind.FunctionDeclaration) return new FunctionDeclarationImpl(peer) - if (kind == api.SyntaxKind.PropertyDeclaration) return new PropertyDeclarationImpl(peer) - if (kind == api.SyntaxKind.Parameter) return new ParameterDeclarationImpl(peer) - - throw new Error(`Unknown node kind: ${kind}`) -} - -export function createIdentifier(name: string, type_annotation?: api.Node): api.Identifier { - const peer = withString(name, (name: string) => { - return type_annotation ? nativeModule._CreateIdentifier2(Global.context, name, getPeer(type_annotation)) : nativeModule._CreateIdentifier1(Global.context, name) - }) - - return new IdentifierImpl(peer) -} - -export function createStringLiteral(s: string): api.StringLiteral { - const peer = withString(s, (s: string) => { - return nativeModule._CreateStringLiteral(Global.context, s) - }) - - return new StringLiteralImpl(peer) -} - -export function createFunctionDeclaration(name: string, parameter_nodes: api.ParameterDeclaration[]): api.FunctionDeclaration { - const parameters = new BigUint64Array(parameter_nodes.map(node => BigInt(getPeer(node)))) - - const peer = withString(name, (name: string) => { - return withPtrArray(parameters, Access.READWRITE, (parameters: BigUint64Array) => { - return nativeModule._CreateFunctionDeclaration(Global.context, name, parameters, parameters.length) - }) - }) - - return new FunctionDeclarationImpl(peer) -} - -export function updateFunctionDeclaration(func: api.FunctionDeclaration, name: api.Identifier, parameter_nodes: api.ParameterDeclaration[]): api.FunctionDeclaration { - const parameters = new BigUint64Array(parameter_nodes.map(node => BigInt(getPeer(node)))) - - const peer = withString(name.text, (name: string) => { - return withPtrArray(parameters, Access.READWRITE, (parameters: BigUint64Array) => { - return nativeModule._UpdateFunctionDeclaration(Global.context, getPeer(func), name, parameters, parameters.length) - }) - }) - - return new FunctionDeclarationImpl(peer) -} - -export function createParameterDeclaration(identifier: api.Identifier): api.ParameterDeclaration { - const peer = nativeModule._CreateETSParameterExpression(Global.context, getPeer(identifier)) - - return new ParameterDeclarationImpl(peer) -} - -export function dumpJson(peer: KNativePointer): string { - return withStringResult(nativeModule._AstNodeDumpJsonConst(Global.context, peer)) ?? throwError(`Couldn't dump to json`) -} - -export function dumpJsonNode(node: api.Node): string { - if (node instanceof NodeImpl) { - return dumpJson(node.peer) - } - throw new Error('node is not from api') -} - -export function getPeer(node: api.Node): KNativePointer { - if (node instanceof NodeImpl) { - return node.peer - } - throw new Error('node is not from api') -} - -export enum Es2pandaPrimitiveType { - PRIMITIVE_TYPE_BYTE = 1, - PRIMITIVE_TYPE_INT = 2, - PRIMITIVE_TYPE_LONG = 3, - PRIMITIVE_TYPE_SHORT = 4, - PRIMITIVE_TYPE_FLOAT = 5, - PRIMITIVE_TYPE_DOUBLE = 6, - PRIMITIVE_TYPE_BOOLEAN = 7, - PRIMITIVE_TYPE_CHAR = 8, - PRIMITIVE_TYPE_VOID = 9, -}; - -export function createETSPrimitiveType(type: Es2pandaPrimitiveType) { - const peer = nativeModule._CreateETSPrimitiveType0(Global.context, type) - - return new ETSPrimitiveTypeImpl(peer) -} - -const keywords = new Map([ - [api.SyntaxKind.NumberKeyword, "number"], - [api.SyntaxKind.StringKeyword, "string"], -]) - -export function createTypeReferenceNode(identifier: api.Identifier): api.TypeReferenceNode { - const type_ref_part = nativeModule._CreateETSTypeReferencePart0(Global.context, getPeer(identifier), BigInt(0), BigInt(0)) - const peer = nativeModule._CreateETSTypeReference0(Global.context, type_ref_part) - return new TypeReferenceNodeImpl(peer) -} - -export function createKeywordTypeNode(TKind: api.KeywordTypeSyntaxKind): api.KeywordTypeNode { - const keyword: string = keywords.get(TKind) ?? throwError('unsupported keyword') - const identifier = withString(keyword, (name: string) => { - return nativeModule._CreateIdentifier1(Global.context, name) - }) - const type_ref_part = nativeModule._CreateETSTypeReferencePart0(Global.context, identifier, BigInt(0), BigInt(0)) - const peer = nativeModule._CreateETSTypeReference0(Global.context, type_ref_part) - return new KeywordTypeNodeImpl(peer) -} diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f8218d44fc702babf8e303a1a2b52723daa5a55 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + SyntaxKind, +} from "@koalaui/ets-tsc" + +import { + Node, + Identifier, + StringLiteral, + FunctionDeclaration, + Block, + KeywordTypeNode, + PropertyAccessExpression, + ParameterDeclaration, + ReturnStatement, + IfStatement, + ExpressionStatement, + CallExpression, + ArrowFunction, + TypeReferenceNode, + BinaryExpression, + BinaryOperatorToken, + ClassDeclaration, + FunctionTypeNode, + TypeNode, + Expression, + Statement, + SourceFile, + ClassElement, + MethodDeclaration, +} from "../types" + +export function isIdentifier(node: Node): node is Identifier { + return node.kind === SyntaxKind.Identifier; +} + +export function isCallExpression(node: Node): node is CallExpression { + return node.kind === SyntaxKind.CallExpression; +} + +export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node.kind === SyntaxKind.PropertyAccessExpression; +} + +export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { + return node.kind === SyntaxKind.FunctionDeclaration; +} + +export function isMethodDeclaration(node: Node): node is MethodDeclaration { + return node.kind === SyntaxKind.MethodDeclaration; +} diff --git a/arkoala-arkts/libarkts/src/arkts/index.ts b/arkoala-arkts/libarkts/src/arkts/index.ts index 965ffbde0654e9d6bf1db3effeb984c301b24032..d40e3a8249db4e8021f846d175ffd3cf836ba9b4 100644 --- a/arkoala-arkts/libarkts/src/arkts/index.ts +++ b/arkoala-arkts/libarkts/src/arkts/index.ts @@ -13,67 +13,7 @@ * limitations under the License. */ -export { - Node, - SyntaxKind, - FunctionDeclaration, - Identifier, - StringLiteral, - SourceFile, - Block, - ExpressionStatement, - ClassDeclaration, - MethodDeclaration, - CallExpression, - PropertyAccessExpression, - NodeFlags, - SourceFileLike, - AsteriskToken, - QuestionToken, - ExclamationToken, - TypeParameterDeclaration, - NodeArray, - ParameterDeclaration, - TypeNode, - Modifier, - __String, - ModifierLike, - Statement, - Token, - AmdDependency, - FileReference, - LanguageVariant, - ScriptTarget, - ModuleKind, - LineAndCharacter, - TextChangeRange, - Expression, - LeftHandSideExpression, - QuestionDotToken, - HeritageClause, - ClassElement, - ObjectLiteralExpression, - PropertyName, - ClassLikeDeclaration, - isSourceFile, - isFunctionDeclaration, - isIdentifier, - isBlock, - isCallExpression, - isExpressionStatement, - isStringLiteral, - isPropertyAccessExpression, - isMethodDeclaration, - isClassDeclaration, - isPropertyDeclaration, - Program, - TransformationContext, - PropertyDeclaration, - TypeParameter, - BindingName, - SignatureDeclaration, - KeywordTypeNode, - KeywordTypeSyntaxKind, - TypeReferenceNode, -} from "typescript" -export * from "./factory/nodeImpls" +export * from "./types" +export * from "./utilities" +export * from "./factory/nodeFactory" +export * from "./factory/nodeTests" diff --git a/arkoala-arkts/libarkts/src/arkts/types.ts b/arkoala-arkts/libarkts/src/arkts/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..d57d80dda6a8b85774eda39c0e28e924c47a8873 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/types.ts @@ -0,0 +1,768 @@ +import * as ts from "@koalaui/ets-tsc" +import { nativeModule } from "../NativeModule" +import { KInt, KNativePointer, withStringResult } from "@koalaui/interop" +import { factory } from "./factory/nodeFactory" +import * as util from "./utilities" + +export const NULLPTR: KNativePointer = BigInt(0) +export const NULLPTR_ARRAY = new BigUint64Array([NULLPTR]) + +// TODO: remove or move out of this file maybe +export enum Es2pandaPrimitiveType { + PRIMITIVE_TYPE_BYTE = 1, + PRIMITIVE_TYPE_INT = 2, + PRIMITIVE_TYPE_LONG = 3, + PRIMITIVE_TYPE_SHORT = 4, + PRIMITIVE_TYPE_FLOAT = 5, + PRIMITIVE_TYPE_DOUBLE = 6, + PRIMITIVE_TYPE_BOOLEAN = 7, + PRIMITIVE_TYPE_CHAR = 8, + PRIMITIVE_TYPE_VOID = 9, +}; + +export enum Es2pandaModifierFlags { + MODIFIER_FLAGS_NONE = 0, + MODIFIER_FLAGS_STATIC = 1 << 0, + MODIFIER_FLAGS_ASYNC = 1 << 1, + MODIFIER_FLAGS_PUBLIC = 1 << 2, + MODIFIER_FLAGS_PROTECTED = 1 << 3, + MODIFIER_FLAGS_PRIVATE = 1 << 4, + MODIFIER_FLAGS_DECLARE = 1 << 5, + MODIFIER_FLAGS_READONLY = 1 << 6, + MODIFIER_FLAGS_OPTIONAL = 1 << 7, + MODIFIER_FLAGS_DEFINITE = 1 << 8, + MODIFIER_FLAGS_ABSTRACT = 1 << 9, + MODIFIER_FLAGS_CONST = 1 << 10, + MODIFIER_FLAGS_FINAL = 1 << 11, + MODIFIER_FLAGS_NATIVE = 1 << 12, + MODIFIER_FLAGS_OVERRIDE = 1 << 13, + MODIFIER_FLAGS_CONSTRUCTOR = 1 << 14, + MODIFIER_FLAGS_SYNCHRONIZED = 1 << 15, + MODIFIER_FLAGS_FUNCTIONAL = 1 << 16, + MODIFIER_FLAGS_IN = 1 << 17, + MODIFIER_FLAGS_OUT = 1 << 18, + MODIFIER_FLAGS_INTERNAL = 1 << 19, + MODIFIER_FLAGS_EXPORT = 1 << 20, + MODIFIER_FLAGS_GETTER = 1 << 21, + MODIFIER_FLAGS_SETTER = 1 << 22, + MODIFIER_FLAGS_DEFAULT_EXPORT = 1 << 23, + MODIFIER_FLAGS_EXPORT_TYPE = 1 << 24, + MODIFIER_FLAGS_SUPER_OWNER = 1 << 25, + MODIFIER_FLAGS_ACCESS = MODIFIER_FLAGS_PUBLIC | MODIFIER_FLAGS_PROTECTED | MODIFIER_FLAGS_PRIVATE | MODIFIER_FLAGS_INTERNAL, + MODIFIER_FLAGS_ALL = MODIFIER_FLAGS_STATIC | MODIFIER_FLAGS_ASYNC | MODIFIER_FLAGS_ACCESS | MODIFIER_FLAGS_DECLARE | MODIFIER_FLAGS_READONLY | MODIFIER_FLAGS_ABSTRACT, + MODIFIER_FLAGS_ALLOWED_IN_CTOR_PARAMETER = MODIFIER_FLAGS_ACCESS | MODIFIER_FLAGS_READONLY, + MODIFIER_FLAGS_INTERNAL_PROTECTED = MODIFIER_FLAGS_INTERNAL | MODIFIER_FLAGS_PROTECTED, + MODIFIER_FLAGS_ACCESSOR_MODIFIERS = MODIFIER_FLAGS_ABSTRACT | MODIFIER_FLAGS_FINAL, + MODIFIER_FLAGS_GETTER_SETTER = MODIFIER_FLAGS_GETTER | MODIFIER_FLAGS_SETTER, + MODIFIER_FLAGS_EXPORTED = MODIFIER_FLAGS_EXPORT | MODIFIER_FLAGS_DEFAULT_EXPORT | MODIFIER_FLAGS_EXPORT_TYPE, +}; + +export const ALL_FLAGS: KInt = Object.values(Es2pandaModifierFlags) +.filter((value: any) => { return (typeof value) === 'number' }) +.reduce( + (prev: KInt, next: KInt): KInt => (prev | next), + 0 as KInt +) + +export { SyntaxKind } from "@koalaui/ets-tsc" + +export class Global { + private static _config?: KNativePointer + + public static set config(config: KNativePointer) { + if (Global._config !== undefined) { + throw new Error('Global.config already initialized') + } + Global._config = config + } + + public static get config(): KNativePointer { + return Global._config ?? util.throwError('Global.config not initialized') + } + + public static isInitializedConfig(): boolean { + return (Global._config !== undefined) + } + + private static _context?: KNativePointer + + public static set context(context: KNativePointer) { + Global._context = context + } + + public static get context(): KNativePointer { + return Global._context ?? util.throwError('Global.context not initialized') + } + + public static isInitializedContext(): boolean { + return (Global._context !== undefined) + } +} + +type Visitor = (node: Node) => Node + +// TODO: rethink +function nodeVisitor(node: T, visitor: Visitor): T { + if (node === undefined) { + return node + } + return visitor(node) as T +} + +// TODO: rethink +function nodesVisitor(nodes: ts.NodeArray | undefined, visitor: Visitor): T[] { + if (nodes === undefined) { + return [] + } + return nodes.map((node: T) => (visitor(node) as T)) +} + +type VisitEachChildFunction = (node: T, visitor: Visitor) => T + +// TODO: add more nodes +type HasChildren = + | SourceFile + | FunctionDeclaration + | ExpressionStatement + | CallExpression + | PropertyAccessExpression + | ClassDeclaration + | MethodDeclaration + | Block + +type VisitEachChildTable = { [TNode in HasChildren as TNode["kind"]]: VisitEachChildFunction } + +// TODO: add more nodes +const visitEachChildTable: VisitEachChildTable = { + [ts.SyntaxKind.SourceFile]: function (node: SourceFile, visitor: Visitor) { + return factory.updateSourceFile( + node, + nodesVisitor(node.statements, visitor) + ) + }, + [ts.SyntaxKind.FunctionDeclaration]: function (node: FunctionDeclaration, visitor: Visitor) { + return factory.updateFunctionDeclaration( + node, + undefined, + undefined, + nodeVisitor(node.name!, visitor), + undefined, + nodesVisitor(node.parameters, visitor), + undefined, + nodeVisitor(node.body, visitor), + ) + }, + [ts.SyntaxKind.ExpressionStatement]: function (node: ExpressionStatement, visitor: Visitor) { + return factory.updateExpressionStatement( + node, + nodeVisitor(node.expression, visitor) + ) + }, + [ts.SyntaxKind.CallExpression]: function (node: CallExpression, visitor: Visitor) { + return factory.updateCallExpression( + node, + nodeVisitor(node.expression, visitor), + undefined, + nodesVisitor(node.arguments, visitor) + ) + }, + [ts.SyntaxKind.PropertyAccessExpression]: function (node: PropertyAccessExpression, visitor: Visitor) { + return factory.updatePropertyAccessExpression( + node, + nodeVisitor(node.expression, visitor), + nodeVisitor(node.name, visitor) as Identifier + ) + }, + [ts.SyntaxKind.ClassDeclaration]: function (node: ClassDeclaration, visitor: Visitor) { + return factory.updateClassDeclaration( + node, + undefined, + nodeVisitor(node.name, visitor), + undefined, + undefined, + nodesVisitor(node.members, visitor) + ) + }, + [ts.SyntaxKind.MethodDeclaration]: function (node: MethodDeclaration, visitor: Visitor) { + return factory.updateMethodDeclaration( + node, + undefined, + undefined, + nodeVisitor(node.name, visitor), + // node.name, + undefined, + undefined, + nodesVisitor(node.parameters, visitor), + // node.parameters, + undefined, + nodeVisitor(node.body, visitor), + // node.body, + ) + }, + [ts.SyntaxKind.Block]: function (node: Block, visitor: Visitor) { + return factory.updateBlock( + node, + nodesVisitor(node.statements, visitor), + ) + }, +} + +function nodeHasChildren(node: ts.Node): node is HasChildren { + return node.kind in visitEachChildTable +} + +export function visitEachChild( + node: T, + visitor: Visitor, + // context: ts.TransformationContext +): T { + const visitFunc = (visitEachChildTable as Record | undefined>)[node.kind]; + if (nodeHasChildren(node) && visitFunc === undefined) { + util.throwError('Unsupported node kind: ' + node.kind) + } + return (visitFunc === undefined) ? node : visitFunc(node, visitor); +} + +function todo(): any { + throw new Error("Not yet implemented") +} + +export abstract class Node implements ts.Node { + peer: KNativePointer + + protected constructor(peer: KNativePointer) { + this.peer = peer + } + + get parent(): Node { + return util.makeView(nativeModule._AstNodeParent(Global.context, this.peer)) + } + + set parent(node: Node) { + nativeModule._AstNodeSetParent(Global.context, this.peer, node.peer) + } + + get modifier(): Es2pandaModifierFlags { + return nativeModule._AstNodeModifiers(Global.context, this.peer) + } + + set modifier(flags: Es2pandaModifierFlags) { + nativeModule._AstNodeClearModifier(Global.context, this.peer, ALL_FLAGS) + nativeModule._AstNodeAddModifier(Global.context, this.peer, flags as KInt) + } + + // TODO: implement + getSourceFile(): ts.SourceFile { throw new Error("Method not implemented.") } + getChildCount(sourceFile?: ts.SourceFile | undefined): number { throw new Error("Method not implemented.") } + getChildAt(index: number, sourceFile?: ts.SourceFile | undefined): ts.Node { throw new Error("Method not implemented.") } + getChildren(sourceFile?: ts.SourceFile | undefined): ts.Node[] { throw new Error("Method not implemented.") } + getStart(sourceFile?: ts.SourceFile | undefined, includeJsDocComment?: boolean | undefined): number { throw new Error("Method not implemented.") } + getFullStart(): number { throw new Error("Method not implemented.") } + getEnd(): number { throw new Error("Method not implemented.") } + getWidth(sourceFile?: ts.SourceFileLike | undefined): number { throw new Error("Method not implemented.") } + getFullWidth(): number { throw new Error("Method not implemented.") } + getLeadingTriviaWidth(sourceFile?: ts.SourceFile | undefined): number { throw new Error("Method not implemented.") } + getFullText(sourceFile?: ts.SourceFile | undefined): string { throw new Error("Method not implemented.") } + getText(sourceFile?: ts.SourceFile | undefined): string { throw new Error("Method not implemented.") } + getFirstToken(sourceFile?: ts.SourceFile | undefined): ts.Node | undefined { throw new Error("Method not implemented.") } + getLastToken(sourceFile?: ts.SourceFile | undefined): ts.Node | undefined { throw new Error("Method not implemented.") } + forEachChild(cbNode: (node: ts.Node) => T | undefined, cbNodeArray?: ((nodes: ts.NodeArray) => T | undefined) | undefined): T | undefined { throw new Error("Method not implemented.") } + + // TODO: support minimal interface + get symbol(): ts.Symbol { return todo() } + get flags(): ts.NodeFlags { return todo() } + get pos(): number { return todo() } + get end(): number { return todo() } + abstract kind: ts.SyntaxKind +} + +export class FunctionDeclaration extends Node implements ts.FunctionDeclaration { + constructor(peer: KNativePointer) { + super(peer) + } + + private get _scriptFunction() { + return nativeModule._FunctionDeclarationFunction(Global.context, this.peer) + } + + get name(): Identifier { + return util.makeView(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier + } + + get body(): Block { + return util.makeView(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + } + + get parameters(): ts.NodeArray { + const params = nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction) + return util.unpack(params) as ts.NodeArray + } + + // TODO: support minimal interface + _functionLikeDeclarationBrand: any + _declarationBrand: any + _statementBrand: any + kind: ts.SyntaxKind.FunctionDeclaration = ts.SyntaxKind.FunctionDeclaration +} + +export class Identifier extends Node implements ts.Identifier, Expression { + constructor(peer: KNativePointer) { + super(peer) + } + + get text(): string { + return withStringResult(nativeModule._IdentifierName(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _IdentifierName`) + } + + // TODO: support minimal interface + get escapedText(): ts.__String { return todo() } + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier +} + +// TODO: should be interface, not abstract class +export abstract class Statement extends Node implements ts.Statement { + _statementBrand: any + kind: any +} + +export class Block extends Node implements ts.Block { + constructor(peer: KNativePointer) { + super(peer) + } + + private _statements?: ts.NodeArray + get statements(): ts.NodeArray { + if (this._statements === undefined) { + const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) + this._statements = util.unpack(statementsPtr) as ts.NodeArray + } + return this._statements + } + + // TODO: support minimal interface + _statementBrand: any + kind: ts.SyntaxKind.Block = ts.SyntaxKind.Block +} + +export class SourceFile extends Node implements ts.SourceFile { + constructor(peer: KNativePointer) { + super(peer) + } + + private _statements?: ts.NodeArray + get statements(): ts.NodeArray { + if (this._statements === undefined) { + const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) + this._statements = util.unpack(statementsPtr) as ts.NodeArray + } + return this._statements + } + + moduleName: string | undefined + getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter { throw new Error("Method not implemented.") } + getLineEndOfPosition(pos: number): number { throw new Error("Method not implemented.") } + getLineStarts(): readonly number[] { throw new Error("Method not implemented.") } + getPositionOfLineAndCharacter(line: number, character: number): number { throw new Error("Method not implemented.") } + update(newText: string, textChangeRange: ts.TextChangeRange): ts.SourceFile { throw new Error("Method not implemented.") } + + // TODO: support minimal interface + get endOfFileToken(): ts.Token { return todo() } + get fileName(): string { return todo() } + get text() { return todo() } + get amdDependencies(): readonly ts.AmdDependency[] { return todo() } + get referencedFiles(): readonly ts.FileReference[] { return todo() } + get typeReferenceDirectives(): readonly ts.FileReference[] { return todo() } + get libReferenceDirectives(): readonly ts.FileReference[] { return todo() } + get languageVariant(): ts.LanguageVariant { return todo() } + get isDeclarationFile(): boolean { return todo() } + get hasNoDefaultLib(): boolean { return todo() } + get languageVersion(): ts.ScriptTarget { return todo() } + _declarationBrand: any + kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile +} + +export abstract class Expression extends Node implements ts.Expression { + _expressionBrand: any + kind: any +} + +export abstract class LeftHandSideExpression extends Node implements ts.LeftHandSideExpression, Expression { + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + kind: any +} + +export class ExpressionStatement extends Node implements ts.ExpressionStatement, Statement { + constructor(peer: KNativePointer) { + super(peer) + } + + get expression(): Expression { + return util.makeView(nativeModule._ExpressionStatementGetExpression(Global.context, this.peer)) as Expression + } + + // TODO: support minimal interface + _statementBrand: any + kind: ts.SyntaxKind.ExpressionStatement = ts.SyntaxKind.ExpressionStatement +} + +export class CallExpression extends Node implements ts.CallExpression, LeftHandSideExpression { + constructor(peer: KNativePointer) { + super(peer) + } + + private _expression?: LeftHandSideExpression + get expression(): LeftHandSideExpression { + if (this._expression === undefined) { + this._expression = util.makeView(nativeModule._CallExpressionCallee(Global.context, this.peer)) as LeftHandSideExpression + } + return this._expression + } + + private _arguments?: ts.NodeArray + get arguments(): ts.NodeArray { + if (this._arguments === undefined) { + const argumentsPtr = nativeModule._CallExpressionArguments(Global.context, this.peer, NULLPTR) + this._arguments = util.unpack(argumentsPtr) as ts.NodeArray + } + return this._arguments + } + + // TODO: support minimal interface + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.CallExpression = ts.SyntaxKind.CallExpression +} + +export class PropertyAccessExpression extends Node implements ts.PropertyAccessExpression, Expression { + constructor(peer: KNativePointer) { + super(peer) + } + + private _name?: Identifier + get name() { + if (this._name === undefined) { + this._name = util.makeView(nativeModule._MemberExpressionProperty(Global.context, this.peer)) as Identifier + } + return this._name + } + + private _expression?: LeftHandSideExpression + get expression(): LeftHandSideExpression { + if (this._expression === undefined) { + this._expression = util.makeView(nativeModule._MemberExpressionObject(Global.context, this.peer)) as LeftHandSideExpression + } + return this._expression + } + + // TODO: support minimal interface + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.PropertyAccessExpression = ts.SyntaxKind.PropertyAccessExpression +} + +export class StringLiteral extends Node implements ts.StringLiteral { + constructor(peer: KNativePointer) { + super(peer) + } + + get text(): string { + return withStringResult(nativeModule._StringLiteralString(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _StringLiteralString`) + } + + // TODO: support minimal interface + _literalExpressionBrand: any + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.StringLiteral = ts.SyntaxKind.StringLiteral +} + +export class ClassDeclaration extends Node implements ts.ClassDeclaration { + constructor(peer: KNativePointer) { + super(peer) + this._definition = nativeModule._ClassDeclarationDefinition(Global.context, peer) + this.members = util.unpack(nativeModule._ClassDefinitionBody(Global.context, this._definition)) as ts.NodeArray + this.name = util.makeView(nativeModule._ClassDefinitionIdent(Global.context, this._definition)) as Identifier + } + + private _definition + + readonly members: ts.NodeArray + readonly name: Identifier + + // TODO: support minimal interface + _declarationBrand: any + _statementBrand: any + kind: ts.SyntaxKind.ClassDeclaration = ts.SyntaxKind.ClassDeclaration; +} + +export class ClassElement extends Node implements ts.ClassElement { + constructor(peer: KNativePointer) { + super(peer) + } + + // tsc: readonly name?: PropertyName; + readonly name?: Identifier; + + // TODO: support minimal interface + _declarationBrand: any + _classElementBrand: any + kind: ts.SyntaxKind.ClassExpression = ts.SyntaxKind.ClassExpression; +} + +// ets: MethodDefinition +export class MethodDeclaration extends Node implements ts.MethodDeclaration { + constructor(peer: KNativePointer) { + super(peer) + this._scriptFunction = nativeModule._MethodDefinitionFunction(Global.context, peer) + this.name = util.makeView(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as ts.NodeArray + this.body = util.makeView(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + } + + // tsc: readonly name?: PropertyName; + readonly name: Identifier + + readonly parameters: ts.NodeArray + + // tsc: readonly body?: FunctionBody | undefined; + readonly body: Block + + private readonly _scriptFunction: KNativePointer + + // TODO: support minimal interface + get parent(): any { return todo() } + _functionLikeDeclarationBrand: any + _classElementBrand: any + _objectLiteralBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.MethodDeclaration = ts.SyntaxKind.MethodDeclaration; +} + +export class PropertyDeclaration extends Node implements ts.PropertyDeclaration { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + get parent(): any { return todo() } + get name(): ts.PropertyName { return todo() } + _classElementBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.PropertyDeclaration = ts.SyntaxKind.PropertyDeclaration; +} + +export class ParameterDeclaration extends Node implements ts.ParameterDeclaration { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + get parent(): any { return todo() } + get name(): ts.BindingName { return todo() } + _declarationBrand: any + kind: ts.SyntaxKind.Parameter = ts.SyntaxKind.Parameter; +} + +export class ETSPrimitiveType extends Node implements ts.Node { + constructor(peer: KNativePointer) { + super(peer) + } + + kind: ts.SyntaxKind.Unknown = ts.SyntaxKind.Unknown; +} + +// TODO: should be interface, not abstract class +export abstract class TypeNode extends Node implements ts.TypeNode { + _typeNodeBrand: any + kind: any +} + +export class KeywordTypeNode extends Node implements ts.KeywordTypeNode, TypeNode { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + _typeNodeBrand: any + kind: ts.KeywordTypeSyntaxKind = ts.SyntaxKind.UnknownKeyword +} + +export class TypeReferenceNode extends Node implements ts.TypeReferenceNode, TypeNode { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + _typeNodeBrand: any + typeName: any + kind: ts.SyntaxKind.TypeReference = ts.SyntaxKind.TypeReference +} + +export class FunctionTypeNode extends Node implements ts.FunctionTypeNode, TypeNode { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + get parent(): any { return todo() } + get parameters(): ts.NodeArray { return todo() } + type: any + _typeNodeBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.FunctionType = ts.SyntaxKind.FunctionType; +} + +export class ReturnStatement extends Node implements ts.ReturnStatement, Statement { + constructor(peer: KNativePointer) { + super(peer) + } + + private _expression?: Expression; + get expression(): Expression | undefined { + if (this._expression === undefined) { + this._expression = util.makeView(nativeModule._ReturnStatementArgument(Global.context, this.peer)) as Expression + } + return this._expression + } + + // TODO: support minimal interface + _statementBrand: any + kind: ts.SyntaxKind.ReturnStatement = ts.SyntaxKind.ReturnStatement; +} + +export class IfStatement extends Node implements ts.IfStatement { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + thenStatement: any + expression: any + _statementBrand: any + kind: ts.SyntaxKind.IfStatement = ts.SyntaxKind.IfStatement; +} + +export class BinaryExpression extends Node implements ts.BinaryExpression { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + left: any + right: any + operatorToken: any + _expressionBrand: any + _declarationBrand: any + kind: ts.SyntaxKind.BinaryExpression = ts.SyntaxKind.BinaryExpression; +} + +// should be Token +export class BinaryOperatorToken extends Node implements ts.BinaryOperatorToken { + constructor(token: ts.TokenSyntaxKind) { + super(NULLPTR) + this._token = BinaryOperatorToken.tokenKinds.get(token) + } + + private static readonly tokenKinds = new Map([ + [ts.SyntaxKind.PlusToken, 26], + ]) + + + private _token: KInt + get token(): KInt { + return this._token + } + + // TODO: support minimal interface + decorators: any + modifiers: any + kind: any +} + +export class ArrowFunction extends Node implements ts.ArrowFunction { + constructor(peer: KNativePointer) { + super(peer) + this._scriptFunction = nativeModule._ArrowFunctionExpressionFunction(Global.context, this.peer) + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as ts.NodeArray + this.body = util.makeView(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + } + + get name(): never { + return this.name + } + + readonly parameters: ts.NodeArray + body: Block + + private _scriptFunction: KNativePointer + + // TODO: support minimal interface + equalsGreaterThanToken: any + _expressionBrand: any + _functionLikeDeclarationBrand: any + _declarationBrand: any + readonly kind: ts.SyntaxKind.ArrowFunction = ts.SyntaxKind.ArrowFunction; +} + +export class NumericLiteral extends Node implements ts.NumericLiteral { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + _literalExpressionBrand: any + _declarationBrand: any + text: any + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + readonly kind: ts.SyntaxKind.NumericLiteral = ts.SyntaxKind.NumericLiteral; +} + +export class VariableStatement extends Node implements ts.VariableStatement { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + modifiers?: ts.NodeArray | undefined + declarationList: any + _statementBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + readonly kind: ts.SyntaxKind.VariableStatement = ts.SyntaxKind.VariableStatement; +} + +export class UnsupportedNode extends Node implements ts.Node { + constructor(peer: KNativePointer) { + super(peer) + } + + kind: ts.SyntaxKind = 0 +} diff --git a/arkoala-arkts/libarkts/src/arkts/utilities.ts b/arkoala-arkts/libarkts/src/arkts/utilities.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0bc30f427054b2fd42a76a1e74aba7f7e548ea0 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/utilities.ts @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ts from "@koalaui/ets-tsc" +import { nativeModule } from "../NativeModule" +import { fromPtrArray, KNativePointer, withString, withStringArray, withStringResult, KInt } from "@koalaui/interop" +import { NativePtrDecoder } from "../node/Platform" +import * as arkts from "./types" + +export function throwError(error: string): never { + throw new Error(error) +} + +/** TODO batch this */ +export function unpack(arrayPtr: KNativePointer): ReadonlyArray { + const array = (new NativePtrDecoder).decode(arrayPtr) + + return fromPtrArray(array, (peer: KNativePointer) => { + return makeView(peer) + }) +} + +export function createConfig(input: string[]): KNativePointer { + return withStringArray(input, (stringArray: string[]) => { + return nativeModule._CreateConfig(input.length, stringArray) + }) +} + +export function createContextFromString(config: KNativePointer, source: string, filename: string): KNativePointer { + return withString(source, (sourcePtr: string) => { + return withString(filename, (filenamePtr: string) => { + return nativeModule._CreateContextFromString(config, sourcePtr, filenamePtr) + }) + }) +} + +export enum ContextState { + ES2PANDA_STATE_NEW = 0, + ES2PANDA_STATE_PARSED = 1, + ES2PANDA_STATE_SCOPE_INITED = 2, + ES2PANDA_STATE_CHECKED = 3, + ES2PANDA_STATE_LOWERED = 4, + ES2PANDA_STATE_ASM_GENERATED = 5, + ES2PANDA_STATE_BIN_GENERATED = 6, + + ES2PANDA_STATE_ERROR = 7, +} + +export function proceedToState(state: ContextState): void { + nativeModule._ProceedToState(arkts.Global.context, state) + if (nativeModule._ContextState(arkts.Global.context) === ContextState.ES2PANDA_STATE_ERROR) { + throwError("FAILED PROCEED TO: " + ContextState[state] + "\n" + withStringResult(nativeModule._ContextErrorMessage(arkts.Global.context)) ?? throwError(`COULDN'T GET: _ContextErrorMessage`)) + } +} + +export function startChecker(): boolean { + return nativeModule._CheckerStartChecker(arkts.Global.context) +} + +export function contextProgram(): KNativePointer { + return nativeModule._ContextProgram(arkts.Global.context) +} + +export function programAst(program: KNativePointer) { // TODO: return type + const nativePtr: KNativePointer = nativeModule._ProgramAst(program) + return nativePtr +} + +enum es2pandaKind { + UnsupportedNode = 0, + + Identifier = 1, + StringLiteral = 2, + Block = 3, + MethodDeclaration = 4, + ClassDeclaration = 5, + FunctionDeclaration = 6, + PropertyDeclaration = 7, + Parameter = 8, + ETSFunctionType = 9, + CallExpression = 10, + ExpressionStatement = 11, + MemberExpression = 12, + ArrowFunctionExpression = 13, + ReturnStatement = 14, + ETSParameterExpression = 15, + NumberLiteral = 16, + VariableDeclaration = 17, + ClassStaticBlock = 18, +} + +const kinds = new Map([ + [es2pandaKind.Identifier, ts.SyntaxKind.Identifier], + [es2pandaKind.StringLiteral, ts.SyntaxKind.StringLiteral], + [es2pandaKind.Block, ts.SyntaxKind.Block], + [es2pandaKind.MethodDeclaration, ts.SyntaxKind.MethodDeclaration], + [es2pandaKind.ClassDeclaration, ts.SyntaxKind.ClassDeclaration], + [es2pandaKind.FunctionDeclaration, ts.SyntaxKind.FunctionDeclaration], + [es2pandaKind.PropertyDeclaration, ts.SyntaxKind.PropertyDeclaration], + [es2pandaKind.ETSFunctionType, ts.SyntaxKind.FunctionType], + [es2pandaKind.CallExpression, ts.SyntaxKind.CallExpression], + [es2pandaKind.ExpressionStatement, ts.SyntaxKind.ExpressionStatement], + [es2pandaKind.MemberExpression, ts.SyntaxKind.PropertyAccessExpression], + [es2pandaKind.ArrowFunctionExpression, ts.SyntaxKind.ArrowFunction], + [es2pandaKind.ReturnStatement, ts.SyntaxKind.ReturnStatement], + // TODO: drop one Parameter (?) + [es2pandaKind.Parameter, ts.SyntaxKind.Parameter], + [es2pandaKind.ETSParameterExpression, ts.SyntaxKind.Parameter], + [es2pandaKind.NumberLiteral, ts.SyntaxKind.NumericLiteral], + [es2pandaKind.VariableDeclaration, ts.SyntaxKind.VariableStatement], + // [es2pandaKind.ClassStaticBlock, ts.SyntaxKind.ClassDeclaration], +]) + +export function makeView(peer: KNativePointer): arkts.Node { + const es2pandaKind = nativeModule._GetKind(peer) + if (nativeModule._IsProgram(arkts.Global.context, peer)) { + return new arkts.SourceFile(peer) + } + + const kind: ts.SyntaxKind | undefined = kinds.get(es2pandaKind) + + if (!kind) { + // console.log(dumpJson(peer)) + // throw new Error(`Unsupported node kind: ${kind}`) + return new arkts.UnsupportedNode(peer) + } + + if (kind == ts.SyntaxKind.Identifier) return new arkts.Identifier(peer) + if (kind == ts.SyntaxKind.StringLiteral) return new arkts.StringLiteral(peer) + if (kind == ts.SyntaxKind.Block) return new arkts.Block(peer) + if (kind == ts.SyntaxKind.MethodDeclaration) return new arkts.MethodDeclaration(peer) + if (kind == ts.SyntaxKind.ClassDeclaration) return new arkts.ClassDeclaration(peer) + if (kind == ts.SyntaxKind.FunctionDeclaration) return new arkts.FunctionDeclaration(peer) + if (kind == ts.SyntaxKind.PropertyDeclaration) return new arkts.PropertyDeclaration(peer) + if (kind == ts.SyntaxKind.FunctionType) return new arkts.FunctionTypeNode(peer) + if (kind == ts.SyntaxKind.CallExpression) return new arkts.CallExpression(peer) + if (kind == ts.SyntaxKind.ExpressionStatement) return new arkts.ExpressionStatement(peer) + if (kind == ts.SyntaxKind.PropertyAccessExpression) return new arkts.PropertyAccessExpression(peer) + if (kind == ts.SyntaxKind.ArrowFunction) return new arkts.ArrowFunction(peer) + if (kind == ts.SyntaxKind.ReturnStatement) return new arkts.ReturnStatement(peer) + if (kind == ts.SyntaxKind.Parameter) return new arkts.ParameterDeclaration(peer) + if (kind == ts.SyntaxKind.NumericLiteral) return new arkts.NumericLiteral(peer) + if (kind == ts.SyntaxKind.VariableStatement) return new arkts.VariableStatement(peer) + + throw new Error(`Unknown node kind: ${kind}`) +} + +export function dumpJson(peer: KNativePointer): string { + return withStringResult(nativeModule._AstNodeDumpJsonConst(arkts.Global.context, peer)) ?? throwError(`COULDN'T DUMP TO JSON`) +} + +export function dumpJsonNode(node: arkts.Node): string { + return dumpJson(node.peer) +} + +export function dumpSrcNode(node: arkts.Node): string { + return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(arkts.Global.context, node.peer)) ?? throwError(`COULDN'T DUMP TO SOURCE`) +} + +export function dumpScriptFunction(peer: KNativePointer) { + return "" + + "ID: " + dumpJson(nativeModule._ScriptFunctionId(arkts.Global.context, peer)) + "\n" + + "BODY: " + dumpJson(nativeModule._ScriptFunctionBody(arkts.Global.context, peer)) + "\n" + + "MODS: " + getModifierFlags(peer) + "\n" +} + +// TODO: remove this getter +export function getPeer(node: arkts.Node): KNativePointer { + return node.peer +} + +// TODO: remove this getter +export function getKind(node: arkts.Node): ts.SyntaxKind { + return node.kind +} + +export function setParent(node: KNativePointer, parent: KNativePointer) { + nativeModule._AstNodeSetParent(arkts.Global.context, node, parent) +} + +export function getModifierFlags(node: KNativePointer): arkts.Es2pandaModifierFlags { + return nativeModule._AstNodeModifiers(arkts.Global.context, node) +} + +export function setModifierFlags(node: KNativePointer, flags: arkts.Es2pandaModifierFlags) { + nativeModule._AstNodeClearModifier(arkts.Global.context, node, arkts.ALL_FLAGS) + nativeModule._AstNodeAddModifier(arkts.Global.context, node, flags as KInt) +} + +export function updateChildren(peer: KNativePointer) { + nativeModule._AstNodeUpdateChildren(arkts.Global.context, peer) +} + +export function getDecl(node: arkts.Node): arkts.Node | undefined { + let decl = node.peer + decl = nativeModule._AstNodeVariableConst(arkts.Global.context, decl) + if (decl === arkts.NULLPTR) { + return undefined + } + decl = nativeModule._VariableDeclaration(arkts.Global.context, decl) + if (decl === arkts.NULLPTR) { + return undefined + } + decl = nativeModule._DeclNode(arkts.Global.context, decl) + if (decl === arkts.NULLPTR) { + return undefined + } + return makeView(decl) +} diff --git a/arkoala-arkts/libarkts/src/es2panda.ts b/arkoala-arkts/libarkts/src/es2panda.ts index 79da6181d505b660a41c2579271daf07780b0250..8c3b0d71d1274c398180eb40d067014595481e62 100644 --- a/arkoala-arkts/libarkts/src/es2panda.ts +++ b/arkoala-arkts/libarkts/src/es2panda.ts @@ -2,6 +2,7 @@ import { Command } from "commander" import * as fs from "fs" import * as path from "path" import * as arkts from "./arkts" +import { generateBinAndRun } from "../test/test-util" function parseCommandLineArgs() { const commander = new Command() @@ -24,20 +25,22 @@ function parseCommandLineArgs() { function es2panda(configPath: string, filePath: string, transform: (ast: arkts.Node) => arkts.Node) { const source = fs.readFileSync(filePath).toString() - const cfg = arkts.createConfig([ + arkts.Global.config = arkts.createConfig([ + '_', '--arktsconfig', configPath, filePath ]) - const ctx = arkts.createContextFromString(cfg, source, filePath) - arkts.proceedToState(ctx, arkts.ContextState.ES2PANDA_STATE_PARSED) - const program = arkts.contextProgram(ctx) + arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, filePath) + arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) + const program = arkts.contextProgram() const peer = arkts.programAst(program) - const ast = arkts.makeView(ctx, peer) + const ast = arkts.makeView(peer) transform(ast) - arkts.proceedToState(ctx, arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) + // TODO: this should be called after executing all plugins + generateBinAndRun() } function plugins(configPath: string): Promise<((ast: arkts.Node) => arkts.Node)[]> { @@ -48,17 +51,21 @@ function plugins(configPath: string): Promise<((ast: arkts.Node) => arkts.Node)[ const pluginPath = jsonPlugin['transform'] // TODO: read and pass plugin options const options = {} - - function webpackUnoptimizableImport(path: string) { - return import(/* webpackIgnore: true */ path) + + function webpackUnoptimizableImport(path: string): { default: any } { + return require(/* webpackIgnore: true */ path) } - // TODO: plugin path relative to arktsconfig - const module = webpackUnoptimizableImport('../../' + pluginPath) - return module.then((plugin) => plugin.default.default(options)()) + + // TODO: fix this require + const module = require('/home/huawei/arkcompiler_ets_frontend/arkoala-arkts/libarkts/compatible/src/example-transformer.ts') + // const module = require(pluginPath) + // const module = webpackUnoptimizableImport(pluginPath) + return module.default("") })) } const { filePath, configPath } = parseCommandLineArgs() + plugins(configPath).then(plugins => { es2panda(configPath, filePath, (ast: arkts.Node) => { return plugins.reduce((ast, plugin) => plugin(ast), ast) diff --git a/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ebd42d4b8defce6440da500d9d8b05c2aa1fff37 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts @@ -0,0 +1,113 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +// tests for abc generation +suite(util.getSuiteTitle(__filename), () => { + test("updating-expression-statement", function() { + const sample_in = + ` + function foo(lambda: (instance: string) => string): void { + console.log(lambda("ABC")) + } + + foo((instance: string) => { return instance }) + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) as arkts.SourceFile + + const expressionStatement = sourceFile.statements[1] as arkts.ExpressionStatement + + const newStatements = [ + sourceFile.statements[0], + arkts.factory.updateExpressionStatement( + expressionStatement, + expressionStatement.expression + ) + ] + + arkts.factory.updateSourceFile(sourceFile, newStatements) + + // util.generateBinAndRun() + }) + + test("updating-function-declaration", function() { + const sample_in = + ` + function foo(): void { + console.log("A") + return + } + + foo() + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) as arkts.SourceFile + + const funcDecl = sourceFile.statements[0] as arkts.FunctionDeclaration + + const newStatements = [ + arkts.factory.updateFunctionDeclaration( + funcDecl, + undefined, + undefined, + funcDecl.name, + undefined, + funcDecl.parameters, + undefined, + funcDecl.body, + ), + sourceFile.statements[1], + ] + + arkts.factory.updateSourceFile(sourceFile, newStatements) + + // util.generateBinAndRun() + }) + + // failing now + test("updating-lambda-call", function() { + const sample_in = + ` + function foo(builder: () => void) {} + foo(() => {}) + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) as arkts.SourceFile + const exprStatement = sourceFile.statements[1] as arkts.ExpressionStatement + const callExpr = exprStatement.expression as arkts.CallExpression + + const lambdaArg = + arkts.factory.createArrowFunction( + undefined, + undefined, + [], + undefined, + undefined, + (callExpr.arguments[0] as arkts.ArrowFunction).body + ) + + const newStatements = [ + sourceFile.statements[0], + arkts.factory.updateExpressionStatement( + exprStatement, + arkts.factory.updateCallExpression( + callExpr, + arkts.factory.updateIdentifier(callExpr.expression as arkts.Identifier, 'foo'), + undefined, + [ + lambdaArg, + ] + ) + ) + ] + arkts.factory.updateSourceFile(sourceFile, newStatements) + + // util.generateBinAndRun() + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a36a7c2732108127f3770a8878ad30e11aa999f1 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts @@ -0,0 +1,219 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { BuilderLambdaTransformer } from "../../compatible/src/builder-lambda-transformer" + +suite(util.getSuiteTitle(__filename), () => { + test("adding-lambda-param-to-signature", function() { + // _Foo((instance: string) => { + // // empty + // }, "label"); + + const sample_in = + ` + Foo("label") + + function Foo(text: string): void { + console.log(text) + } + ` + + util.getDefaultSetup(sample_in) + + const newName = "_Foo" + const paramName = "instance" + + const node = (arkts.makeView(util.getStatement(0)) as arkts.ExpressionStatement).expression as arkts.CallExpression + + const instanceLambdaBody = arkts.factory.createBlock([]) + const lambdaParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier(paramName, arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword)) + ) + ] + + const lambda = arkts.factory.createArrowFunction( + undefined, + undefined, + lambdaParams, + undefined, + undefined, + instanceLambdaBody + ) + + const result = arkts.factory.updateCallExpression( + node, + arkts.factory.createIdentifier(newName), + undefined, + [ + lambda, + ...node.arguments + ] + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(result), this) + + const sample_out = + ` + _Foo(((instance: string) => {}), "label") + ` + util.assertEqualsSource(arkts.dumpSrcNode(result), sample_out) + }) + + test("adding-body-to-lambda-param", function() { + // _Foo((instance: string) => { + // instance.bar().qux(); + // }, "label1", "label2"); + + const sample_in = + ` + Foo(instance.bar().qux(), "label1", "label2") + ` + + util.getDefaultSetup(sample_in) + + const newName = "_Foo" + const paramName = "instance" + + const node = (arkts.makeView(util.getStatement(0)) as arkts.ExpressionStatement).expression as arkts.CallExpression + + const instanceLambdaBody = arkts.factory.createBlock([ + arkts.factory.createExpressionStatement( + node.arguments[0] + ) + ]) + const lambdaParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier(paramName, arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword)) + ) + ] + + const lambda = arkts.factory.createArrowFunction( + undefined, + undefined, + lambdaParams, + undefined, + undefined, + instanceLambdaBody + ) + + const result = arkts.factory.updateCallExpression( + node, + arkts.factory.createIdentifier(newName), + undefined, + [ + lambda, + ...node.arguments.slice(1) + ] + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(result), this) + + const sample_out = + ` + _Foo(((instance: string) => { + instance.bar().qux(); + }), "label1", "label2") + ` + util.assertEqualsSource(arkts.dumpSrcNode(result), sample_out) + }) + + test("builder-lambda-transformer-sample-1", function() { + // foo((instance: string) => { + // return instance; + // }, "label"); + + const sample_in = + ` + _BuilderLambdaCall_foo("label") + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) + const builderLambdaTransformer = new BuilderLambdaTransformer() + + const transformed = builderLambdaTransformer.visitor(sourceFile) + + util.assertEqualsGolden(arkts.dumpJsonNode(transformed), this) + + const sample_out = + ` + foo(((instance: string) => { + return instance; + }), "label") + ` + util.assertEqualsSource(arkts.dumpSrcNode(transformed), sample_out) + }) + + test("builder-lambda-transformer-sample-2", function() { + // foo((instance: string) => { + // return instance.bar().qux(); + // }, "label1", "label2"); + + const sample_in = + ` + _BuilderLambdaCall_foo("label1", "label2").bar().qux() + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) + const builderLambdaTransformer = new BuilderLambdaTransformer() + + const transformed = builderLambdaTransformer.visitor(sourceFile) + + util.assertEqualsGolden(arkts.dumpJsonNode(transformed), this) + + const sample_out = + ` + foo(((instance: string) => { + return instance.bar().qux(); + }), "label1", "label2") + ` + util.assertEqualsSource(arkts.dumpSrcNode(transformed), sample_out) + }) + + // TODO: update nodes properly (now failing to generate bin) + test("builder-lambda-transformer-sample-3", function() { + // function Foo(builder: (instance: string) => string, arg1: string): void { + // console.log(arg1 + builder("ABC")) + // } + // Foo((instance: string) => { + // return instance.charAt(1) + // }, "> second_char_of_ABC: ") + + const sample_in = + ` + function Foo(builder: (instance: string) => string, arg1: string): void { + console.log(arg1 + builder("ABC")) + } + + _BuilderLambdaCall_Foo("> second_char_of_ABC: ").charAt(1) + ` + + util.getDefaultSetup(sample_in) + + const sourceFile = arkts.makeView(util.AstProvider.provideAst()) + const builderLambdaTransformer = new BuilderLambdaTransformer() + + const transformed = builderLambdaTransformer.visitor(sourceFile) + + util.assertEqualsGolden(arkts.dumpJsonNode(transformed), this) + + const sample_out = + ` + function Foo(builder: ((instance: string)=> string), arg1: string): void { + console.log(((arg1) + (builder("ABC")))); + } + + Foo(((instance: string) => { + return instance.charAt(1); + }), "> second_char_of_ABC: ") + ` + util.assertEqualsSource(arkts.dumpSrcNode(transformed), sample_out) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts b/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts index 5fe15c199c0bc3ed76574335269792e251762b34..aca03cffd8dae2e6a2ebcf31203e77a748e2dbba 100644 --- a/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts @@ -1,5 +1,5 @@ import * as util from "../test-util" -import * as api from "../../src/arkts" +import * as arkts from "../../src/arkts" suite(util.getSuiteTitle(__filename), () => { test("empty-function", function() { @@ -7,24 +7,109 @@ suite(util.getSuiteTitle(__filename), () => { // // empty // } - util.getDefaultSetup('') + const sample_in = `` + + util.getDefaultSetup(sample_in) - const funcDecl = api.createFunctionDeclaration("test_func", []) + const funcDecl = arkts.factory.createFunctionDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("test_func"), + undefined, + [], + undefined, + arkts.factory.createBlock( + [], + true + ) + ) - util.assertEqualsGolden(api.dumpJsonNode(funcDecl), this) + util.assertEqualsGolden(arkts.dumpJsonNode(funcDecl), this) + + const sample_out = + ` + function test_func() {} + ` + util.assertEqualsSource(arkts.dumpSrcNode(funcDecl), sample_out) }) test("empty-function-with-param", function() { - // function test_func(x: number) { + // function test_func(x: long) { // // empty // } util.getDefaultSetup('') + const sourceFile: arkts.SourceFile = arkts.makeView(util.AstProvider.provideAst()) as arkts.SourceFile + + const typeAnnotation = arkts.factory.createEtsPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_INT) + const funcParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("x", typeAnnotation) + ) + ] + const funcDecl = arkts.factory.createFunctionDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("test_func"), + undefined, + funcParams, + undefined, + arkts.factory.createBlock( + [], + true + ) + ) + + arkts.factory.updateSourceFile(sourceFile, [funcDecl]) + + util.assertEqualsGolden(arkts.dumpJsonNode(sourceFile), this) + + const sample_out = + ` + function test_func(x: long) {} + ` + util.assertEqualsSource(arkts.dumpSrcNode(sourceFile), sample_out) + }) + + test("empty-function-with-string-param", function() { + // function test_func(x: string) { + // // empty + // } + + util.getDefaultSetup('') + const sourceFile: arkts.SourceFile = arkts.makeView(util.AstProvider.provideAst()) as arkts.SourceFile + + const typeAnnotation = arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + const funcParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("x", typeAnnotation) + ) + ] + const funcDecl = arkts.factory.createFunctionDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("test_func"), + undefined, + funcParams, + undefined, + arkts.factory.createBlock( + [], + true + ) + ) + + arkts.factory.updateSourceFile(sourceFile, [funcDecl]) - const typeAnnotation = api.createKeywordTypeNode(api.SyntaxKind.NumberKeyword) - const funcParams = [api.createParameterDeclaration(api.createIdentifier("x", typeAnnotation))] - const funcDeclaration = api.createFunctionDeclaration("test_func", funcParams) + util.assertEqualsGolden(arkts.dumpJsonNode(sourceFile), this) - util.assertEqualsGolden(api.dumpJsonNode(funcDeclaration), this) + const sample_out = + ` + function test_func(x: string) {} + ` + util.assertEqualsSource(arkts.dumpSrcNode(sourceFile), sample_out) }) }) diff --git a/arkoala-arkts/libarkts/test/es2panda/create-node.test.ts b/arkoala-arkts/libarkts/test/es2panda/create-node.test.ts deleted file mode 100644 index 3eee20cd001c010d0fc038c5bc8d65e9056ed6f2..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/test/es2panda/create-node.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as util from "../test-util" -import * as api from "../../src/arkts" - -suite(util.getSuiteTitle(__filename), () => { - test("create-and-check-string-literal", function() { - util.getDefaultSetup('') - - const strStringLiteral = "string-literal-text" - const node = api.createStringLiteral(strStringLiteral) - - util.assert.equal(node.text, strStringLiteral) - util.assert.isTrue(api.isStringLiteral(node)) - util.assertEqualsGolden(api.dumpJsonNode(node), this) - }) -}) diff --git a/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4064d703a8732bde6670f428434eff87f99e5112 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts @@ -0,0 +1,36 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { FunctionTransformer } from "../../compatible/src/function-transformer" + +// TODO: update scopes (transforming after check) +suite(util.getSuiteTitle(__filename), () => { + test("function-transformer-sample-1", function() { + const sample_in = + ` + const x: string = "A" + + function _REWRITE_foo() { + console.log("FUNC CALLED: " + x) + } + + _REWRITE_foo() + ` + + // util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + // const sourceFile = arkts.makeView(util.AstProvider.provideAst()) + + // const memoTransformer = new FunctionTransformer() + // const transformed = memoTransformer.visitor(sourceFile) + + // util.nativeModule._VarBinderInitTopScope(arkts.Global.context) + // util.nativeModule._VarBinderIdentifierAnalysis(arkts.Global.context) + // console.log(arkts.startChecker()) + + // console.log(arkts.dumpSrcNode(sourceFile)) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..66032ff4eebf8fa39e9a1aa5b246978a65a3948e --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts @@ -0,0 +1,138 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + // full memo rewrite + test("memo-function-with-lambda-memo-param", function() { + // function foo( + // __memo_context: __memo_context_type, + // __memo_id: __memo_id_type, + // content: (__memo_context: __memo_context_type, __memo_id: __memo_id_type) => void + // ) { + // if (__memo_scope.unchanged) + // return __memo_scope.cached + // content(__memo_context, __memo_id + "key_id_main.ts") + // return __memo_scope.recache() + // } + + const sample_in = + ` + function foo( + content: () => void + ) { + content() + } + ` + + util.getDefaultSetup(sample_in) + + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + arkts.factory.createIfStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("unchanged") + ), + arkts.factory.createReturnStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("cached") + ) + ), + undefined + ), + arkts.factory.createExpressionStatement( + arkts.factory.createCallExpression( + arkts.factory.createIdentifier("content"), + undefined, + [ + arkts.factory.createIdentifier("__memo_context"), + arkts.factory.createBinaryExpression( + arkts.factory.createIdentifier("__memo_id"), + arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + arkts.factory.createStringLiteral("key_id_main.ts") + ) + ] + )), + arkts.factory.createReturnStatement( + arkts.factory.createCallExpression( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("recache") + ) + ) + ) + ] + + testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) + + const newLambdaParams = [ + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("__memo_context"), + undefined, + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("__memo_context_type"), + undefined + ) + ), + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("__memo_id"), + undefined, + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("__memo_id_type"), + undefined + ), + ) + ] + + const newLambdaParam = arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("content"), + undefined, + arkts.factory.createFunctionTypeNode( + undefined, + newLambdaParams, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.VoidKeyword) + ), + undefined + ) + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + [ + testFunc.parameters[0], + testFunc.parameters[1], + newLambdaParam + ], + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, content: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)) { + if (__memo_scope.unchanged) { + return __memo_scope.cached; + } + content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); + return __memo_scope.recache(); + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..de19f47f37f738581a8f2c23b586df55f3b418b7 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts @@ -0,0 +1,27 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { MemoTransformer } from "../../compatible/src/memo-transformer" + +suite(util.getSuiteTitle(__filename), () => { + test("memo-transformer-sample-1", function() { + const sample_in = + ` + function _MEMO_foo() { + console.log("MEMO FUNC CALLED!") + } + + _MEMO_foo() + ` + + // util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + // const sourceFile = arkts.makeView(util.AstProvider.provideAst()) + + // const memoTransformer = new MemoTransformer() + // const transformed = memoTransformer.visitor(sourceFile) + + // console.log(arkts.dumpSrcNode(sourceFile)) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/visitor.test.ts b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts similarity index 54% rename from arkoala-arkts/libarkts/test/es2panda/visitor.test.ts rename to arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts index 31af0cf649af23cd0c8d838afee3518639e79dfc..ea271c29764f23fc942506d5b481d26a3638dcc7 100644 --- a/arkoala-arkts/libarkts/test/es2panda/visitor.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts @@ -1,9 +1,9 @@ -import * as api from "../../src/arkts" +import * as arkts from "../../src/arkts" import * as util from "../test-util" import { PrintVisitor } from "../../compatible/src/print-visitor" -suite("visitor test", () => { - test("class & methods", () => { +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { const source = ` class Base { @@ -26,19 +26,41 @@ function main(): void { ` SourceFile ClassDeclaration + Identifier PropertyDeclaration MethodDeclaration + Identifier + Block + ExpressionStatement + UnsupportedNode MethodDeclaration + Identifier + Block ClassDeclaration + Identifier MethodDeclaration + Identifier + Block FunctionDeclaration + Identifier + Block FunctionDeclaration + Identifier + Block FunctionDeclaration + Identifier + Block + VariableStatement + ExpressionStatement + CallExpression + PropertyAccessExpression + Identifier + Identifier ` util.getDefaultSetup(source) const peer = util.AstProvider.provideAst() - const ast = api.makeView(peer) + const ast = arkts.makeView(peer) const output = (new PrintVisitor()).astToString(ast) util.assert.equal(output.trim(), expected.trim()) diff --git a/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts b/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts index 7c7bf9fc0798acb6d32ce30812a44b012231fc67..a6c6d6e8cadc59d587e1a3a1254c001ca0e21cc0 100644 --- a/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts @@ -1,8 +1,13 @@ import * as util from "../test-util" -import * as api from "../../src/arkts" +import * as arkts from "../../src/arkts" suite(util.getSuiteTitle(__filename), () => { + // adding y: string to signature test("update-name-and-add-param-to-function", function() { + // function new_test_func(x: number, y: string) { + // // empty + // } + const sample_in = ` function test_func(x: number) { @@ -10,25 +15,39 @@ suite(util.getSuiteTitle(__filename), () => { } ` - // adding y: string to signature - - // function new_test_func(x: number, y: string) { - // // empty - // } - util.getDefaultSetup(sample_in) - let testFunc = api.makeView(util.getStatement(0)) as api.FunctionDeclaration + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration const oldParams = testFunc.parameters - const newParamTypeAnnotation = api.createKeywordTypeNode(api.SyntaxKind.StringKeyword) - const newParam = api.createParameterDeclaration(api.createIdentifier("y", newParamTypeAnnotation)) + const newParamTypeAnnotation = arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + const newParam = arkts.factory.createParameterDeclaration(undefined, undefined, arkts.factory.createIdentifier("y", newParamTypeAnnotation)) const newParams = [...oldParams, newParam] - api.updateFunctionDeclaration(testFunc, api.createIdentifier("new_test_func"), newParams) + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + arkts.factory.createIdentifier("new_test_func"), + undefined, + newParams, + undefined, + testFunc.body + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) - util.assertEqualsGolden(api.dumpJsonNode(testFunc), this) + const sample_out = + ` + function new_test_func(x: number, y: string) {} + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) }) + // adding memo params to signature test("add-params-to-memo-function", function() { + // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, x: number) { + // // empty + // } + const sample_in = ` function foo(x: number) { @@ -36,23 +55,327 @@ suite(util.getSuiteTitle(__filename), () => { } ` - // adding memo params to signature + util.getDefaultSetup(sample_in) - // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, x: number) { - // // empty + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, x: number) {} + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) + + // adding identifier x + test("add-identifier-to-function-body", function() { + // function foo() { + // x // } + const sample_in = + ` + function foo() { + // empty + } + ` + util.getDefaultSetup(sample_in) - let testFunc = api.makeView(util.getStatement(0)) as api.FunctionDeclaration - const oldParams = testFunc.parameters - const memoContextAnnotation = api.createTypeReferenceNode(api.createIdentifier("__memo_context_type")) - const memoContextParam = api.createParameterDeclaration(api.createIdentifier("__memo_context", memoContextAnnotation)) - const memoIdAnnotation = api.createTypeReferenceNode(api.createIdentifier("__memo_id_type")) - const memoIdParam = api.createParameterDeclaration(api.createIdentifier("__memo_id", memoIdAnnotation)) - const newParams = [memoContextParam, memoIdParam, ...oldParams] - api.updateFunctionDeclaration(testFunc, testFunc.name!, newParams) - - util.assertEqualsGolden(api.dumpJsonNode(testFunc), this) + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + ...testFunc.body.statements, + arkts.factory.createExpressionStatement(arkts.factory.createIdentifier("x")) + ] + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + testFunc.parameters, + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo() { + x; + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) + + // adding __memo_scope.recache + test("add-property-access-expression-to-function-body", function() { + // function foo() { + // __memo_scope.recache + // } + + const sample_in = + ` + function foo() { + // empty + } + ` + + util.getDefaultSetup(sample_in) + + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + ...testFunc.body.statements, + arkts.factory.createExpressionStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("recache") + ) + ) + ] + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + testFunc.parameters, + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo() { + __memo_scope.recache; + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) + + // body memo rewrite (adding return statement) + test("add-return-statement-to-function-body", function() { + // function foo() { + // // if (__memo_scope.unchanged) + // // return __memo_scope.cached + // // content(__memo_context, __memo_id + "key_id_main.ts") + // return __memo_scope.recache() + // } + + const sample_in = + ` + function foo() { + // empty + } + ` + + util.getDefaultSetup(sample_in) + + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + ...testFunc.body.statements, + arkts.factory.createReturnStatement( + arkts.factory.createCallExpression( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("recache") + ) + ) + ) + ] + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + testFunc.parameters, + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) as arkts.FunctionDeclaration + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo() { + return __memo_scope.recache(); + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) + + // body memo rewrite (adding if statement) + test("add-if-statement-to-function-body", function() { + // function foo() { + // if (__memo_scope.unchanged) + // return __memo_scope.cached + // // content(__memo_context, __memo_id + "key_id_main.ts") + // // return __memo_scope.recache() + // } + + const sample_in = + ` + function foo() { + // empty + } + ` + + util.getDefaultSetup(sample_in) + + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + arkts.factory.createIfStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("unchanged") + ), + arkts.factory.createReturnStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("cached") + ) + ), + undefined + ), + ...testFunc.body.statements + ] + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + testFunc.parameters, + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo() { + if (__memo_scope.unchanged) { + return __memo_scope.cached; + } + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) + }) + + // body memo rewrite + test("function-declaration-memo-rewrite", function() { + // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { + // if (__memo_scope.unchanged) + // return __memo_scope.cached + // content(__memo_context, __memo_id + "key_id_main.ts") + // return __memo_scope.recache() + // } + + const sample_in = + ` + function foo() { + // empty + } + ` + + util.getDefaultSetup(sample_in) + + let testFunc = arkts.makeView(util.getStatement(0)) as arkts.FunctionDeclaration + + let body_statements = [ + arkts.factory.createIfStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("unchanged") + ), + arkts.factory.createReturnStatement( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("cached") + ) + ), + undefined + ), + arkts.factory.createExpressionStatement( + arkts.factory.createCallExpression( + arkts.factory.createIdentifier("content"), + undefined, + [ + arkts.factory.createIdentifier("__memo_context"), + arkts.factory.createBinaryExpression( + arkts.factory.createIdentifier("__memo_id"), + arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + arkts.factory.createStringLiteral("key_id_main.ts") + ) + ] + )), + arkts.factory.createReturnStatement( + arkts.factory.createCallExpression( + arkts.factory.createPropertyAccessExpression( + arkts.factory.createIdentifier("__memo_scope"), + arkts.factory.createIdentifier("recache") + ) + ) + ), + ...testFunc.body.statements + ] + + testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) + + testFunc = arkts.factory.updateFunctionDeclaration( + testFunc, + undefined, + undefined, + testFunc.name, + undefined, + testFunc.parameters, + undefined, + arkts.factory.updateBlock( + testFunc.body, + body_statements + ) + ) as arkts.FunctionDeclaration + + util.assertEqualsGolden(arkts.dumpJsonNode(testFunc), this) + + const sample_out = + ` + function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { + if (__memo_scope.unchanged) { + return __memo_scope.cached; + } + content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); + return __memo_scope.recache(); + } + ` + util.assertEqualsSource(arkts.dumpSrcNode(testFunc), sample_out) }) }) diff --git a/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-body-to-lambda-param.test.ts_dump b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-body-to-lambda-param.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..e02b4c13d6c1cd5ead9824a83d15bbbb8deb784c --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-body-to-lambda-param.test.ts_dump @@ -0,0 +1,93 @@ +{ + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "_Foo", + "decorators": [] + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "instance", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "bar", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + }, + "property": { + "type": "Identifier", + "name": "qux", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + } + } + }, + { + "type": "StringLiteral", + "value": "label1" + }, + { + "type": "StringLiteral", + "value": "label2" + } + ], + "optional": false +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-lambda-param-to-signature.test.ts_dump b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-lambda-param-to-signature.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..d7e34adeab7869e043d4ef6601e9737b07e35a0f --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_adding-lambda-param-to-signature.test.ts_dump @@ -0,0 +1,50 @@ +{ + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "_Foo", + "decorators": [] + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [] + } + } + }, + { + "type": "StringLiteral", + "value": "label" + } + ], + "optional": false +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-1.test.ts_dump b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-1.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..bb25e742de59c84d84163b1bf3ba1fea9ba0ac33 --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-1.test.ts_dump @@ -0,0 +1,67 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "instance", + "decorators": [] + } + } + ] + } + } + }, + { + "type": "StringLiteral", + "value": "label" + } + ], + "optional": false + } + } + ] +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-2.test.ts_dump b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-2.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..74d03b766980c3892626a6ab8255591c11f679ba --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-2.test.ts_dump @@ -0,0 +1,101 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "instance", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "bar", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + }, + "property": { + "type": "Identifier", + "name": "qux", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + } + } + }, + { + "type": "StringLiteral", + "value": "label1" + }, + { + "type": "StringLiteral", + "value": "label2" + } + ], + "optional": false + } + } + ] +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-3.test.ts_dump b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-3.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..b5b55ac2ffb7b58557fb0022b5756ee4edf3288e --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/builder-lambda-rewrite_builder-lambda-transformer-sample-3.test.ts_dump @@ -0,0 +1,221 @@ +{ + "type": "Program", + "statements": [ + { + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "Foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "builder", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + } + }, + "decorators": [] + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "returnType": { + "type": "ETSPrimitiveType" + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "console", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "log", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "arg1", + "decorators": [] + }, + "right": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "builder", + "decorators": [] + }, + "arguments": [ + { + "type": "StringLiteral", + "value": "ABC" + } + ], + "optional": false + } + } + ], + "optional": false + } + } + ] + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "Foo", + "decorators": [] + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "instance", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "instance", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1 + } + ], + "optional": false + } + } + ] + } + } + }, + { + "type": "StringLiteral", + "value": "> second_char_of_ABC: " + } + ], + "optional": false + } + } + ] +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-param.test.ts_dump b/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-param.test.ts_dump index 28b4b8cb0869bc51788813629a6ee28e1a7f950a..9e31147884294121eb52aa0afcbbafbab7685720 100644 --- a/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-param.test.ts_dump +++ b/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-param.test.ts_dump @@ -1,39 +1,36 @@ { - "type": "FunctionDeclaration", - "function": { - "type": "ScriptFunction", - "id": { - "type": "Identifier", - "name": "test_func", - "decorators": [] - }, - "generator": false, - "async": false, - "expression": false, - "params": [ - { - "type": "ETSParameterExpression", - "name": { + "type": "Program", + "statements": [ + { + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { "type": "Identifier", - "name": "x", - "typeAnnotation": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "number", - "decorators": [] - } - } - }, + "name": "test_func", "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSPrimitiveType" + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [] } } - ], - "body": { - "type": "BlockStatement", - "statements": [] } - } + ] } \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-string-param.test.ts_dump b/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-string-param.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..613b7e83fea339077208dae4fb5028e998b5b382 --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/create-function-declaration_empty-function-with-string-param.test.ts_dump @@ -0,0 +1,44 @@ +{ + "type": "Program", + "statements": [ + { + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "test_func", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [] + } + } + } + ] +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/create-node_create-and-check-string-literal.test.ts_dump b/arkoala-arkts/libarkts/test/golden/create-node_create-and-check-string-literal.test.ts_dump deleted file mode 100644 index 804d4b5579b0119df1a303f27933eed63f681120..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/test/golden/create-node_create-and-check-string-literal.test.ts_dump +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "StringLiteral", - "value": "string-literal-text" -} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/lambda-param-memoization_memo-function-with-lambda-memo-param.test.ts_dump b/arkoala-arkts/libarkts/test/golden/lambda-param-memoization_memo-function-with-lambda-memo-param.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..332d3c89bd1225869030556287ed59c612b9ccb9 --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/lambda-param-memoization_memo-function-with-lambda-memo-param.test.ts_dump @@ -0,0 +1,205 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_context", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_context_type", + "decorators": [] + } + } + }, + "decorators": [] + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_id", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_id_type", + "decorators": [] + } + } + }, + "decorators": [] + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "content", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_context", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_context_type", + "decorators": [] + } + } + }, + "decorators": [] + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_id", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_id_type", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "returnType": { + "type": "ETSPrimitiveType" + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "unchanged", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "consequent": { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "cached", + "decorators": [] + }, + "computed": false, + "optional": false + } + }, + "alternate": null + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "content", + "decorators": [] + }, + "arguments": [ + { + "type": "Identifier", + "name": "__memo_context", + "decorators": [] + }, + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "__memo_id", + "decorators": [] + }, + "right": { + "type": "StringLiteral", + "value": "key_id_main.ts" + } + } + ], + "optional": false + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "recache", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-identifier-to-function-body.test.ts_dump b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-identifier-to-function-body.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..44d4b6777b0133567102c1c3620f148d5e683d7b --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-identifier-to-function-body.test.ts_dump @@ -0,0 +1,28 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Identifier", + "name": "x", + "decorators": [] + } + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-if-statement-to-function-body.test.ts_dump b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-if-statement-to-function-body.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..1a1578cdf8d927eba45c089b5b9ba970231acb0b --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-if-statement-to-function-body.test.ts_dump @@ -0,0 +1,57 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "unchanged", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "consequent": { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "cached", + "decorators": [] + }, + "computed": false, + "optional": false + } + }, + "alternate": null + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-property-access-expression-to-function-body.test.ts_dump b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-property-access-expression-to-function-body.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..f7d17b74f6f2b56eeda22d9313d49352894e754c --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-property-access-expression-to-function-body.test.ts_dump @@ -0,0 +1,38 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "recache", + "decorators": [] + }, + "computed": false, + "optional": false + } + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-return-statement-to-function-body.test.ts_dump b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-return-statement-to-function-body.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..7b5560cff7918252569ada462128daec835e8169 --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/update-function-declaration_add-return-statement-to-function-body.test.ts_dump @@ -0,0 +1,43 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "recache", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/golden/update-function-declaration_function-declaration-memo-rewrite.test.ts_dump b/arkoala-arkts/libarkts/test/golden/update-function-declaration_function-declaration-memo-rewrite.test.ts_dump new file mode 100644 index 0000000000000000000000000000000000000000..aa97fb990b4249a13ba0bef13960856d82f74714 --- /dev/null +++ b/arkoala-arkts/libarkts/test/golden/update-function-declaration_function-declaration-memo-rewrite.test.ts_dump @@ -0,0 +1,151 @@ +{ + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [] + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_context", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_context_type", + "decorators": [] + } + } + }, + "decorators": [] + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "__memo_id", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "__memo_id_type", + "decorators": [] + } + } + }, + "decorators": [] + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "unchanged", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "consequent": { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "cached", + "decorators": [] + }, + "computed": false, + "optional": false + } + }, + "alternate": null + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "content", + "decorators": [] + }, + "arguments": [ + { + "type": "Identifier", + "name": "__memo_context", + "decorators": [] + }, + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "__memo_id", + "decorators": [] + }, + "right": { + "type": "StringLiteral", + "value": "key_id_main.ts" + } + } + ], + "optional": false + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "__memo_scope", + "decorators": [] + }, + "property": { + "type": "Identifier", + "name": "recache", + "decorators": [] + }, + "computed": false, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + } + } +} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/test-util.ts b/arkoala-arkts/libarkts/test/test-util.ts index 4193af150c5c76dacefa5dafb51daa67ad79b84e..58e6f99cc1ea9670826098622d8cccd51e495c16 100644 --- a/arkoala-arkts/libarkts/test/test-util.ts +++ b/arkoala-arkts/libarkts/test/test-util.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import * as api from "../src/arkts" +import * as arkts from "../src/arkts" import * as fs from "fs" import * as path from "path" import { KNativePointer } from "@koalaui/interop" @@ -21,34 +21,36 @@ import { nativeModule } from "../src/NativeModule" import { NativePtrDecoder } from "../src/node/Platform" import { assert } from "chai" -function getDefaultConfigFileName(): string { - return "./input/main.ts" -} - -function getDefaultConfig() { - const arktsconfig = "./arktsconfig.json" - return ["--arktsconfig", arktsconfig, getDefaultConfigFileName()] +class DefaultConfig { + static readonly configFile = "./arktsconfig.json" + static readonly sourceFile = "./input/main.sts" + static readonly config = ["", "--arktsconfig", this.configFile, this.sourceFile] } export function getDefaultSetup(source: string): void { - if (!api.Global.isInitializedConfig()) { - api.Global.config = api.createConfig(getDefaultConfig()) + if (!arkts.Global.isInitializedConfig()) { + arkts.Global.config = arkts.createConfig(DefaultConfig.config) } - api.Global.context = api.createContextFromString(api.Global.config, source, getDefaultConfigFileName()) + arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, DefaultConfig.sourceFile) + arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) } export class AstProvider { public static provideAst(): KNativePointer { - api.proceedToState(api.ContextState.ES2PANDA_STATE_PARSED) - const program = api.contextProgram() - const peer = api.programAst(program) + const program = arkts.contextProgram() + const peer = arkts.programAst(program) return peer } } +export function alignText(text: string): string { + // TODO: remove spaces/tabs at the beginning of each line + return text +} + export function getStatement(index: number): KNativePointer { const peer = AstProvider.provideAst() - return (new NativePtrDecoder()).decode(nativeModule._BlockStatementStatements(api.Global.context, peer))[index] + return (new NativePtrDecoder()).decode(nativeModule._BlockStatementStatements(arkts.Global.context, peer))[index] } export function getSuiteTitle(fileName: string) { @@ -68,5 +70,52 @@ export function assertEqualsGolden(text: string, testCtx: Mocha.Context) { assert.equal(text, loadGoldenDump(testCtx.test!.parent!.title, testCtx.test!.title)) } +export function assertEqualsSource(sourceResult: string, sourceExpect: string) { + assert.equal( + sourceResult.trim().split('\n').map((line: string) => line.trim()).join('\n'), + sourceExpect.trim().split('\n').map((line: string) => line.trim()).join('\n') + ) +} + +export function dumpFirst() { + return arkts.dumpJson(getStatement(0)) +} + +export function addMemoParamsToFunctionDeclaration(func: arkts.FunctionDeclaration): arkts.FunctionDeclaration { + const oldParams = func.parameters + const memoContextAnnotation = arkts.factory.createTypeReferenceNode(arkts.factory.createIdentifier("__memo_context_type")) + const memoContextParam = arkts.factory.createParameterDeclaration(undefined, undefined, arkts.factory.createIdentifier("__memo_context", memoContextAnnotation)) + const memoIdAnnotation = arkts.factory.createTypeReferenceNode(arkts.factory.createIdentifier("__memo_id_type")) + const memoIdParam = arkts.factory.createParameterDeclaration(undefined, undefined, arkts.factory.createIdentifier("__memo_id", memoIdAnnotation)) + const newParams = [memoContextParam, memoIdParam, ...oldParams] + return arkts.factory.updateFunctionDeclaration( + func, + undefined, + undefined, + func.name!, + undefined, + newParams, + undefined, + func.body + ) +} + +export function generateBinAndRun() { + arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) + const { exec } = require('child_process'); + exec('rm ./native/main.abc') + exec('mv ./main.abc ./native/main.abc') + exec('npm run run:abc', + (err: any, stdout: any, stderr: any) => { + if (err) { + console.log('failed to run abc') + return; + } + console.log(`stdout: ${stdout}`); + console.log(`stderr: ${stderr}`); + }); + +} + export { nativeModule } from "../src/NativeModule" export { assert } from "chai"