diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eaaddce22870394f366dc1d29e05ab89bf9e0bdc..3d0aabdc7daea245287ae8fa7db80246d42fd94c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ image: "nexus.bz-openlab.ru:10443/huawei/koala-ci:0.2" stages: - prebuild - build-compiler + - build-plugin-api - build - test - idlize @@ -20,8 +21,8 @@ include: - incremental/compiler-plugin/.gitlab-ci.yml - incremental/runtime/.gitlab-ci.yml - incremental/demo-playground/.gitlab-ci.yml - - arkoala/tools/peer-generator/.gitlab-ci.yml - - arkoala-arkts/user/.gitlab-ci.yml + - arkoala/arkui/.gitlab-ci.yml + - arkoala-arkts/libarkts/.gitlab-ci.yml unmemoize arkoala-arkts/arkui: allow_failure: true diff --git a/arkoala-arkts/libarkts/.gitlab-ci.yml b/arkoala-arkts/libarkts/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..baadfeb5d79ddc155ce57b612ff313d01bbdf54a --- /dev/null +++ b/arkoala-arkts/libarkts/.gitlab-ci.yml @@ -0,0 +1,41 @@ +# 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. + +build plugin-api: + stage: build + interruptible: true + extends: .linux-vm-shell-task + before_script: + - !reference [.setup, script] + - cd arkoala-arkts/libarkts + script: + - npm i && npm run compile + artifacts: + expire_in: 2 days + paths: + - arkoala-arkts/libarkts/compatible/build + - arkoala-arkts/libarkts/compatible/build_arkts + - arkoala-arkts/libarkts/native/build_es2panda + +test plugin-api: + stage: test + allow_failure: true + interruptible: true + extends: .linux-vm-shell-task + before_script: + - !reference [.setup, script] + - cd arkoala-arkts/libarkts + script: + - npm i && npm run test + needs: + - build plugin-api diff --git a/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts index 68ac3dd86772068618528cd77787132315df934d..7d8dddbaa0a7a01c3d76f0593f0fbdd60feacb9b 100644 --- a/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts +++ b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" export abstract class AbstractVisitor { @@ -40,3 +40,4 @@ export abstract class AbstractVisitor { ) } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts b/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts new file mode 100644 index 0000000000000000000000000000000000000000..41910f71f880ae8099bd32ce4f0565835175724a --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts @@ -0,0 +1,258 @@ +/* + * 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"; + +import { Rewrite } from './transformation-context'; +import { + FunctionKind, + Tracer, + // findSourceFile, + // error, + asString, + RuntimeNames, + // isFunctionOrMethod, + // getComment, + // arrayAt, + // getDeclarationsByNode, + findFunctionDeclaration, + // isMemoEntry, + // skipParenthesizedExpression, +} from "./util" +// import { ImportExport } from './import-export'; + +function parseComment(comment: string): FunctionKind { + let kind = FunctionKind.REGULAR + if (comment.includes(RuntimeNames.ANNOTATION_INTRINSIC)) { + kind = FunctionKind.MEMO_INTRINSIC + } else if (comment.includes(RuntimeNames.ANNOTATION_ENTRY)) { + // Do nothing + } else if (comment.includes(RuntimeNames.ANNOTATION)) { + kind = FunctionKind.MEMO + } + return kind +} + +export class AnalysisVisitor extends AbstractVisitor { + constructor( + public tracer: Tracer, + // public typechecker: arkts.TypeChecker, + // public sourceFile: arkts.SourceFile, + public rewrite: Rewrite, + ctx?: arkts.TransformationContext + ) { + super(ctx) + } + + // private importExport = new ImportExport(this.typechecker, this.sourceFile) + + trace(msg: any) { + this.tracer.trace(msg) + } + + traceAnnotation(nodeName: string, kind: FunctionKind, node: arkts.Node) { + if (kind) { + this.trace(`${nodeName} HAS annotation: ${asString(node)} to ${FunctionKind[kind]}`) + } else { + this.trace(`${nodeName} doesn't have annotations: ${asString(node)}`) + } + } + + // TODO: get real annotation + getFunctionKindByIdent(node: arkts.Identifier | undefined, traceAnnotation: string): FunctionKind { + if (node === undefined) { + return FunctionKind.REGULAR + } + if (!arkts.isIdentifier(node)) { + arkts.throwError('node expected to be Identifier') + } + const kind = parseComment(node.text) + this.traceAnnotation(traceAnnotation, kind, node) + return kind + } + + updateFunctionTableByKind(node: arkts.SignatureDeclarationBase, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.functionTable.set(node, kind) + } + + updateFunctionTableByIdent(node: arkts.SignatureDeclarationBase, ident: arkts.Identifier | undefined, traceMessage: string): void { + if (ident === undefined) { + return + } + this.updateFunctionTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + updateVariableTableByKind(node: arkts.VariableLikeDeclaration, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.variableTable.set(node, kind) + } + + updateVariableTableByIdent(node: arkts.VariableLikeDeclaration, ident: arkts.Identifier, traceMessage: string): void { + this.updateVariableTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + updateCallTableByKind(node: arkts.CallExpression, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.callTable.set(node, kind) + } + + updateCallTableByIdent(node: arkts.CallExpression, ident: arkts.Identifier, traceMessage: string): void { + this.updateCallTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + isMemoEntry(node: arkts.CallExpression): boolean { + const enclosingFunction = findFunctionDeclaration(node) + if (enclosingFunction === undefined) { + return false + } + return this.getFunctionKindByIdent(enclosingFunction.name, "isMemoEntry") === FunctionKind.MEMO + } + + processCallExpression(node: arkts.CallExpression): void { + if (arkts.isIdentifier(node.expression)) { + this.updateCallTableByIdent(node, node.expression, "CallExpression") + } else if (arkts.isPropertyAccessExpression(node.expression)) { + // TODO: fix maybe (copied from compiler-plugin) + const kind = this.getFunctionKindByIdent(node.expression.name, "CallExpression") + if (kind !== FunctionKind.REGULAR) { + this.rewrite.callTable.set(node, kind) + } + return + } + if (this.isMemoEntry(node)) { + this.rewrite.entryTable.add(node) + } + } + + processFunctionDeclaration(node: arkts.FunctionDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "FunctionDeclaration") + } + + processMethodDeclaration(node: arkts.MethodDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "MethodDeclaration") + } + + // TODO: unavailable now (ArrowFunction doesn't have a name) + processArrowFunction(node: arkts.ArrowFunction): void { + // this.updateFunctionTableByIdent(node, node.name, "ArrowFunction") + return + } + + processFunctionExpression(node: arkts.FunctionExpression): void { + this.updateFunctionTableByIdent(node, node.name, "MethodDeclaration") + } + + processParameter(node: arkts.ParameterDeclaration): void { + this.updateVariableTableByIdent(node, node.name, "ParameterDeclaration") + } + + processVariableDeclaration(node: arkts.VariableDeclaration): void { + this.updateVariableTableByIdent(node, node.name, "ParameterDeclaration") + } + + processVariableDeclarationList(node: arkts.VariableDeclarationList): void { + node.declarations.forEach(declaration => { + this.processVariableDeclaration(declaration) + }) + } + + processPropertyDeclaration(node: arkts.PropertyDeclaration): void { + // TODO: support non Identifier properties + this.updateVariableTableByIdent(node, node.name as arkts.Identifier, "PropertyDeclaration") + } + + processPropertySignature(node: arkts.PropertySignature): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateVariableTableByIdent(node, node.name as arkts.Identifier, "PropertySignature") + } + + processFunctionTypeNode(node: arkts.FunctionTypeNode): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateFunctionTableByIdent(node, node.name as arkts.Identifier, "FunctionTypeNode") + } + + processMethodSignature(node: arkts.MethodSignature): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateFunctionTableByIdent(node, node.name as arkts.Identifier, "MethodSignature") + } + + processGetAccessorDeclaration(node: arkts.GetAccessorDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "GetAccessorDeclaration") + } + + processSetAccessorDeclaration(node: arkts.SetAccessorDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "SetAccessorDeclaration") + } + + visitor(node: arkts.Node): arkts.Node { + // TODO: comparison shouldn't work now + if (arkts.getOriginalNode(node) !== node) { + throw new Error("Analysis phase is expected to work on original nodes") + } + + if (arkts.isCallExpression(node)) { + this.processCallExpression(node) + } else if (arkts.isFunctionDeclaration(node)) { + this.processFunctionDeclaration(node) + } else if (arkts.isMethodDeclaration(node)) { + this.processMethodDeclaration(node) + } else if (arkts.isArrowFunction(node)) { + this.processArrowFunction(node) + } else if (arkts.isFunctionExpression(node)) { + this.processFunctionExpression(node) + } else if (arkts.isParameter(node)) { + this.processParameter(node) + } + // else if (arkts.isVariableDeclaration(node)) { + // this.processVariableDeclaration(node) + // } + else if (arkts.isVariableDeclarationList(node)) { + this.processVariableDeclarationList(node) + } + else if (arkts.isPropertyDeclaration(node)) { + this.processPropertyDeclaration(node) + } else if (arkts.isPropertySignature(node)) { + this.processPropertySignature(node) + } else if (arkts.isFunctionTypeNode(node)) { + this.processFunctionTypeNode(node) + } else if (arkts.isMethodSignature(node)) { + this.processMethodSignature(node) + } else if (arkts.isGetAccessorDeclaration(node)) { + this.processGetAccessorDeclaration(node) + } else if (arkts.isSetAccessorDeclaration(node)) { + this.processSetAccessorDeclaration(node) + } + + return this.visitEachChild(node) + } +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts index 83ff1e8ce52e33cbc68cc3185eac287cd66907b2..0a72cbefaa53e394db48ed77884a3f3e461ff769 100644 --- a/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -48,7 +48,7 @@ export class BuilderLambdaTransformer extends AbstractVisitor { return node } - let instanceCalls = [] + let instanceCalls: arkts.CallExpression[] = [] let leaf: arkts.CallExpression = node while (true @@ -125,3 +125,4 @@ export class BuilderLambdaTransformer extends AbstractVisitor { ) } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts index 2c67fb0661b653f9d82f1db4325612b1ac74aded..d267f6e453fb8a1720252f9f10885e7e803f8a21 100644 --- a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import { BuilderLambdaTransformer } from "./builder-lambda-transformer" @@ -15,3 +16,4 @@ export default function exampleTransformer(program?: arkts.Program, userPluginOp } } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/function-transformer.ts b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts index d0f436e826a8f3882b15b323a831c0f9de266c9b..6e6d61eab1c0bb9d2c2ba9850a81a413d6c4f834 100644 --- a/arkoala-arkts/libarkts/compatible/src/function-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -97,3 +97,4 @@ export class FunctionTransformer extends AbstractVisitor { return node } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts index 19c7d060dae10fb67968550d39af3b4f884db760..b32004b4ff9e3e2a0c6745c0238dd96ab9671d17 100644 --- a/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -100,13 +100,15 @@ function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { ) ] )), - ...node.body.statements, + ...(node.body?.statements ?? []), arkts.factory.createReturnStatement( arkts.factory.createCallExpression( arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ), ] @@ -126,10 +128,11 @@ function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { ...node.parameters ], undefined, + node.body ? arkts.factory.updateBlock( node.body, bodyStatements - ) + ) : undefined ) } @@ -152,3 +155,4 @@ export class MemoTransformer extends AbstractVisitor { return node } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts index 240ba96822296bc9cfa32964ce991f18cca4e018..7865d20e7b1b340f55e5cb1e82c0d4b104173dcc 100644 --- a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts +++ b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -15,7 +16,7 @@ export class PrintVisitor extends AbstractVisitor { } visitor(beforeChildren: arkts.Node): arkts.Node { - this.print(beforeChildren.constructor.name + " (mod: " + beforeChildren.modifier + ")") + this.print(beforeChildren.constructor.name + " (mods: [" + beforeChildren.modifiers + "])") const node = this.visitEachChild(beforeChildren) return node @@ -27,3 +28,4 @@ export class PrintVisitor extends AbstractVisitor { return this.result.trim() } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/transformation-context.ts b/arkoala-arkts/libarkts/compatible/src/transformation-context.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab47648083e7d29cb4e66da47b2893d69bf21c4a --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/transformation-context.ts @@ -0,0 +1,36 @@ +/* + * 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 { CallTable, EntryTable, FunctionKind, FunctionTable, TransformerOptions, VariableTable } from "./util" + +export class Rewrite { + public functionTable: FunctionTable + public callTable: CallTable + public variableTable: VariableTable + public entryTable: EntryTable + // public positionalIdTracker: PositionalIdTracker + + constructor(sourceFile: arkts.SourceFile, public pluginOptions: TransformerOptions) { + this.functionTable = new Map() + this.callTable = new Map() + this.variableTable = new Map() + this.entryTable = new Set() + // this.positionalIdTracker = new PositionalIdTracker(sourceFile, pluginOptions.stableForTest ?? false) + } + + public importTypesFrom: string | undefined = undefined +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/util.ts b/arkoala-arkts/libarkts/compatible/src/util.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8622f4b2fea14a42569eeb3989a6bff3ad4a91d --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/util.ts @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2022-2024 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 * as fs from "fs" + +export enum FunctionKind { + REGULAR, + MEMO, + MEMO_INTRINSIC, +} + +export type FunctionTable = Map +export type CallTable = Map +export type EntryTable = Set +export type VariableTable = Map + +export function isNamedDeclaration(node: arkts.Node): node is arkts.NamedDeclaration { + return ("name" in node ) +} + +export function asString(node: arkts.Node | undefined): string { + if (node === undefined) { + return "undefined node" + } + if (arkts.isIdentifier(node)) { + return node.text + } + if (isNamedDeclaration(node)) { + if (node.name === undefined) { + return `${arkts.SyntaxKind[node.kind]}(undefined name)` + } else { + return `${arkts.SyntaxKind[node.kind]}(${asString(node.name)})` + } + } else { + return `${arkts.SyntaxKind[node.kind]}` + } +} + +export function isFunctionOrMethod(node: arkts.Node): node is arkts.FunctionLikeDeclaration { + return arkts.isFunctionDeclaration(node) || + arkts.isMethodDeclaration(node) || + arkts.isFunctionExpression(node) || + arkts.isArrowFunction(node) +} + +export interface TransformerOptions { + // Emit transformed functions to the console. + trace?: boolean, + // Store the transformed functions to this directory. + keepTransformed?: string, + // Use human readable call site IDs without directory paths. + stableForTest?: boolean, + // Import context and id types from alternative source + contextImport?: string, + // Dump sources with resolved memo annotations to unmemoized directory + only_unmemoize?: boolean, + // Replace extension for output TS files + extension?: string, +} + +function baseName(path: string): string { + return path.replace(/^.*\/(.*)$/, "$1") +} + +export class Tracer { + constructor ( + public options: TransformerOptions, + // TODO: implement ts.Printer + // public printer: arkts.Printer + ) {} + + trace(msg: any) { + if (!this.options.trace) return + console.log(msg) + } + + writeTextToFile(text: string, file: string) { + fs.writeFileSync(file, text, 'utf8') + this.trace("DUMP TO: " + file) + } + + createDirs(dirs: string) { + fs.mkdirSync(dirs, { recursive: true }); + } + + dumpFileName(sourceFile: arkts.SourceFile, transformed: arkts.FunctionLikeDeclarationBase): string | undefined { + if (!this.options.keepTransformed) { + return undefined + } + + const outDir = (this.options.keepTransformed[0] == "/") ? + this.options.keepTransformed : + `${__dirname}/${this.options.keepTransformed}` + + this.createDirs(outDir) + + const sourceBaseName = baseName(sourceFile.fileName) + if (!transformed.name) return + if (!arkts.isIdentifier(transformed.name)) return + const fileName = `${transformed.name.text}_${sourceBaseName}` + return `${outDir}/${fileName}_dump` + } + + keepTransformedFunction(transformed: arkts.FunctionLikeDeclarationBase, sourceFile: arkts.SourceFile) { + const fileName = this.dumpFileName(sourceFile, transformed) + if (!fileName) return + + // TODO: implement ts.Printer + // const content = this.printer.printNode(arkts.EmitHint.Unspecified, transformed, sourceFile) + // this.writeTextToFile(content+"\n", fileName) + } +} + +export enum RuntimeNames { + // COMPUTE = "compute", + // CONTEXT = "__memo_context", + // ID = "__memo_id", + // SCOPE = "__memo_scope", + // INTERNAL_PARAMETER_STATE = "param", + // INTERNAL_VALUE = "cached", + // INTERNAL_VALUE_NEW = "recache", + // INTERNAL_SCOPE = "scope", + // INTERNAL_VALUE_OK = "unchanged", + // CONTENT = "content", + // VALUE = "value", + // __CONTEXT = "__context", + // __ID = "__id", + // __KEY = "__key", + // __STATE = "__state", + // CONTEXT_TYPE = "__memo_context_type", + // ID_TYPE = "__memo_id_type", + // TRANSFORMED_TYPE = "__memo_transformed", + // SYNTHETIC_RETURN_MARK = "__synthetic_return_value", + // CONTEXT_TYPE_DEFAULT_IMPORT = "@koalaui/runtime", + ANNOTATION = "_memo", + ANNOTATION_INTRINSIC = "_memo:intrinsic", + ANNOTATION_ENTRY = "_memo:entry", + ANNOTATION_SKIP = "_skip:memo", // skip binding to parameter changes + ANNOTATION_STABLE = "_memo:stable", // assume this should not be tracked +} + +export function findFunctionDeclaration(node: arkts.Node): arkts.FunctionDeclaration | undefined { + while (node.kind !== arkts.SyntaxKind.SourceFile) { + if (arkts.isFunctionDeclaration(node)) { + return node + } + node = node.parent + } + return undefined +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/input/export.sts b/arkoala-arkts/libarkts/input/export.sts new file mode 100644 index 0000000000000000000000000000000000000000..d5f7c542e436e4b5a82ea4498e90b9b3af4f9a70 --- /dev/null +++ b/arkoala-arkts/libarkts/input/export.sts @@ -0,0 +1,5 @@ +export function foo() { + console.log("Hello, world!") +} + +export const TEST: double = 2.718281828459045; diff --git a/arkoala-arkts/libarkts/native/meson.build b/arkoala-arkts/libarkts/native/meson.build index 9a34a36772192bcbb822262c6a0b96264993fb40..76a00282321059cbd03d4b40328a966c9ff12eb1 100644 --- a/arkoala-arkts/libarkts/native/meson.build +++ b/arkoala-arkts/libarkts/native/meson.build @@ -50,8 +50,8 @@ sources += [ interop_src / 'napi/convertors-napi.cc', ] -node_addon_api = run_command('node', '-p', 'require.resolve("node-addon-api/package.json").slice(0, -12)', check: true).stdout().strip() -node_api_headers = run_command('node', '-p', 'require.resolve("node-api-headers/package.json").slice(0, -12)', check: true).stdout().strip() +node_addon_api = '../node_modules/node-addon-api' +node_api_headers = '../node_modules/node-api-headers' include_dirs += [ interop_src / 'napi', diff --git a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc index 957c293324bc4d5e68b919bee2779ff6f9f8bff0..32030e7c3dfe390d7ea2b1d006e935931ad23e69 100644 --- a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc +++ b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc @@ -104,6 +104,13 @@ KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) { } KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray) +KNativePointer impl_DestroyConfig(KNativePointer configPtr) { + auto config = reinterpret_cast(configPtr); + GetImpl()->DestroyConfig(config); + return nullptr; +} +KOALA_INTEROP_1(DestroyConfig, KNativePointer, KNativePointer) + KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr sourcePtr, KStringPtr filenamePtr) { auto source = getString(sourcePtr); auto filename = getString(filenamePtr); @@ -112,6 +119,13 @@ KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr } KOALA_INTEROP_3(CreateContextFromString, KNativePointer, KNativePointer, KStringPtr, KStringPtr) +KNativePointer impl_DestroyContext(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + GetImpl()->DestroyContext(context); + return nullptr; +} +KOALA_INTEROP_1(DestroyContext, KNativePointer, KNativePointer) + KNativePointer impl_ProceedToState(KNativePointer contextPtr, KInt state) { auto context = reinterpret_cast(contextPtr); return GetImpl()->ProceedToState(context, intToState(state)); @@ -169,6 +183,14 @@ KNativePointer impl_CreateIdentifier1(KNativePointer contextPtr, KStringPtr name } KOALA_INTEROP_2(CreateIdentifier1, KNativePointer, KNativePointer, KStringPtr) +KNativePointer impl_IdentifierSetName(KNativePointer contextPtr, KNativePointer nodePtr, KStringPtr namePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + GetImpl()->IdentifierSetName(context, node, getStringCopy(namePtr)); + return node; +} +KOALA_INTEROP_3(IdentifierSetName, KNativePointer, KNativePointer, KNativePointer, KStringPtr) + KNativePointer impl_CreateIdentifier2(KNativePointer contextPtr, KStringPtr namePtr, KNativePointer typeAnnotationPtr) { auto context = reinterpret_cast(contextPtr); auto typeAnnotation = reinterpret_cast(typeAnnotationPtr); @@ -191,18 +213,32 @@ KNativePointer impl_CreateETSFunctionTypeIr(KNativePointer contextPtr, KNativePo } KOALA_INTEROP_3(CreateETSFunctionTypeIr, KNativePointer, KNativePointer, KNativePointer, KInt) +KNativePointer impl_CreateNumberLiteral(KNativePointer contextPtr, KStringPtr strPtr) { + auto context = reinterpret_cast(contextPtr); + + return GetImpl()->CreateNumberLiteral(context, getStringCopy(strPtr)); +} +KOALA_INTEROP_2(CreateNumberLiteral, KNativePointer, KNativePointer, KStringPtr) + KNativePointer impl_CreateStringLiteral(KNativePointer contextPtr, KStringPtr stringPtr) { auto context = reinterpret_cast(contextPtr); return GetImpl()->CreateStringLiteral1(context, getStringCopy(stringPtr)); } KOALA_INTEROP_2(CreateStringLiteral, KNativePointer, KNativePointer, KStringPtr) -KNativePointer impl_StringLiteralString(KNativePointer contextPtr, KNativePointer nodePtr) { +KNativePointer impl_StringLiteralStrConst(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); return new string(GetImpl()->StringLiteralStrConst(context, node)); } -KOALA_INTEROP_2(StringLiteralString, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_2(StringLiteralStrConst, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_NumberLiteralStrConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return new string(GetImpl()->NumberLiteralStrConst(context, node)); +} +KOALA_INTEROP_2(NumberLiteralStrConst, KNativePointer, KNativePointer, KNativePointer) KNativePointer impl_CreateMethodDefinition( KNativePointer contextPtr, @@ -272,12 +308,18 @@ enum AstNodeKind { BinaryExpression = 20, FunctionExpression = 21, ScriptFunction = 22, + VariableDeclarator = 23, + TSTypeParameter = 24, + ETSPrimitiveType = 25, + AssignmentExpression = 26, + ETSTypeReference = 27, + TSUnionType = 28, + ETSUnionType = 29, + ClassDefinition = 30, + ETSTypeReferencePart = 31, }; static KInt GetKind(es2panda_Context* context, es2panda_AstNode* node) { - if (GetImpl()->AstNodeIsProgramConst(context, node)) { - return AstNodeKind::Program; - } if (GetImpl()->IsIdentifier(node)) { return AstNodeKind::Identifier; } @@ -341,7 +383,37 @@ static KInt GetKind(es2panda_Context* context, es2panda_AstNode* node) { if (GetImpl()->IsScriptFunction(node)) { return AstNodeKind::ScriptFunction; } + if (GetImpl()->IsVariableDeclarator(node)) { + return AstNodeKind::VariableDeclarator; + } + if (GetImpl()->IsTSTypeParameter(node)) { + return AstNodeKind::TSTypeParameter; + } + if (GetImpl()->IsETSPrimitiveType(node)) { + return AstNodeKind::ETSPrimitiveType; + } + if (GetImpl()->IsAssignmentExpression(node)) { + return AstNodeKind::AssignmentExpression; + } + if (GetImpl()->IsETSTypeReference(node)) { + return AstNodeKind::ETSTypeReference; + } + if (GetImpl()->IsTSUnionType(node)) { + return AstNodeKind::TSUnionType; + } + if (GetImpl()->IsETSUnionType(node)) { + return AstNodeKind::ETSUnionType; + } + if (GetImpl()->IsClassDefinition(node)) { + return AstNodeKind::ClassDefinition; + } + if (GetImpl()->IsETSTypeReferencePart(node)) { + return AstNodeKind::ETSTypeReferencePart; + } + if (GetImpl()->AstNodeIsProgramConst(context, node)) { + return AstNodeKind::Program; + } return 0; } @@ -375,6 +447,15 @@ KNativePointer impl_BlockStatementStatements(KNativePointer contextPtr, KNativeP } KOALA_INTEROP_2(BlockStatementStatements, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_VariableDeclarationDeclaratorsConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + size_t n; + auto declarators = GetImpl()->VariableDeclarationDeclaratorsConst(context, node, &n); + return new vector(declarators, declarators + n); +} +KOALA_INTEROP_2(VariableDeclarationDeclaratorsConst, 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); @@ -401,6 +482,14 @@ KNativePointer impl_ClassDefinitionBody(KNativePointer contextPtr, KNativePointe } KOALA_INTEROP_2(ClassDefinitionBody, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ClassDefinitionTypeParamsConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return const_cast(GetImpl()->ClassDefinitionTypeParamsConst(context, node)); +} +KOALA_INTEROP_2(ClassDefinitionTypeParamsConst, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_FunctionDeclarationFunction(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -408,6 +497,14 @@ KNativePointer impl_FunctionDeclarationFunction(KNativePointer contextPtr, KNati } KOALA_INTEROP_2(FunctionDeclarationFunction, KNativePointer, KNativePointer, KNativePointer) +KBoolean impl_FunctionDeclarationIsAnonymousConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->FunctionDeclarationIsAnonymousConst(context, node); +} +KOALA_INTEROP_2(FunctionDeclarationIsAnonymousConst, KBoolean, KNativePointer, KNativePointer) + KNativePointer impl_ScriptFunctionParams(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -417,6 +514,22 @@ KNativePointer impl_ScriptFunctionParams(KNativePointer contextPtr, KNativePoint } KOALA_INTEROP_2(ScriptFunctionParams, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ScriptFunctionTypeParams(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionTypeParams(context, node); +} +KOALA_INTEROP_2(ScriptFunctionTypeParams, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionReturnTypeAnnotation(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionReturnTypeAnnotation(context, node); +} +KOALA_INTEROP_2(ScriptFunctionReturnTypeAnnotation, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_ScriptFunctionId(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -456,13 +569,124 @@ KNativePointer impl_UpdateFunctionDeclaration( KOALA_INTEROP_4(UpdateFunctionDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KBoolean) // TODO: add param initializer -KNativePointer impl_CreateETSParameterExpression(KNativePointer contextPtr, KNativePointer identifierPtr) { +KNativePointer impl_CreateETSParameterExpression(KNativePointer contextPtr, KNativePointer identifierPtr, KNativePointer initializerPtr) { auto context = reinterpret_cast(contextPtr); auto identifier = reinterpret_cast(identifierPtr); + auto initializer = reinterpret_cast(initializerPtr); + + return GetImpl()->CreateETSParameterExpression(context, identifier, initializer); +} +KOALA_INTEROP_3(CreateETSParameterExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateTSTypeParameterDeclaration( + KNativePointer contextPtr, + KNativePointerArray paramsPtr, + KInt paramsLen, + KInt requiredParams +) { + auto context = reinterpret_cast(contextPtr); + auto params = reinterpret_cast(paramsPtr); + + return GetImpl()->CreateTSTypeParameterDeclaration(context, params, paramsLen, requiredParams); +} +KOALA_INTEROP_4(CreateTSTypeParameterDeclaration, KNativePointer, KNativePointer, KNativePointerArray, KInt, KInt) + +KNativePointer impl_TSTypeParameterDeclarationParamsConst(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()->TSTypeParameterDeclarationParamsConst(context, node, ¶ms_len); + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(TSTypeParameterDeclarationParamsConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateVariableDeclaration( + KNativePointer contextPtr, + KInt kindT, + KNativePointerArray declaratorsPtr, + KInt declaratorsLen, + KBoolean declareT +) { + auto context = reinterpret_cast(contextPtr); + auto kind = static_cast(kindT); + auto declarators = reinterpret_cast(declaratorsPtr); + auto declare = static_cast(declareT); + + return GetImpl()->CreateVariableDeclaration(context, kind, declarators, declaratorsLen, declare); +} +KOALA_INTEROP_5(CreateVariableDeclaration, KNativePointer, KNativePointer, KInt, KNativePointerArray, KInt, KBoolean) + +KNativePointer impl_UpdateVariableDeclaration( + KNativePointer contextPtr, + KNativePointer originalPtr, + KInt kindT, + KNativePointerArray declaratorsPtr, + KInt declaratorsLen, + KBoolean declareT +) { + auto context = reinterpret_cast(contextPtr); + auto original = reinterpret_cast(originalPtr); + auto kind = static_cast(kindT); + auto declarators = reinterpret_cast(declaratorsPtr); + auto declare = static_cast(declareT); + + return GetImpl()->UpdateVariableDeclaration(context, original, kind, declarators, declaratorsLen, declare); +} +KOALA_INTEROP_6(UpdateVariableDeclaration, KNativePointer, KNativePointer, KNativePointer, KInt, KNativePointerArray, KInt, KBoolean) + +KNativePointer impl_CreateVariableDeclarator( + KNativePointer contextPtr, + KInt flagT, + KNativePointer identPtr +) { + auto context = reinterpret_cast(contextPtr); + auto flag = static_cast(flagT); + auto ident = reinterpret_cast(identPtr); + + return GetImpl()->CreateVariableDeclarator(context, flag, ident); +} +KOALA_INTEROP_3(CreateVariableDeclarator, KNativePointer, KNativePointer, KInt, KNativePointer) - return GetImpl()->CreateETSParameterExpression(context, identifier, nullptr); +KNativePointer impl_VariableDeclaratorSetInit(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer initPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto init = reinterpret_cast(initPtr); + + GetImpl()->VariableDeclaratorSetInit(context, node, init); + return node; +} +KOALA_INTEROP_3(VariableDeclaratorSetInit, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_VariableDeclaratorId(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->VariableDeclaratorId(context, node); +} +KOALA_INTEROP_2(VariableDeclaratorId, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateTSTypeParameter( + KNativePointer contextPtr, + KNativePointer namePtr, + KNativePointer constraintPtr, + KNativePointer defaultTypePtr +) { + auto context = reinterpret_cast(contextPtr); + auto name = reinterpret_cast(namePtr); + auto constraint = reinterpret_cast(constraintPtr); + auto defaultType = reinterpret_cast(defaultTypePtr); + + return GetImpl()->CreateTSTypeParameter(context, name, constraint, defaultType); } -KOALA_INTEROP_2(CreateETSParameterExpression, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_4(CreateTSTypeParameter, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_TSTypeParameterName(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->TSTypeParameterName(context, node); +} +KOALA_INTEROP_2(TSTypeParameterName, KNativePointer, KNativePointer, KNativePointer) KNativePointer impl_ETSParameterExpressionIdent(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); @@ -656,7 +880,10 @@ KNativePointer impl_UpdateCallExpression( auto optional = static_cast(optionalT); auto trailingComma = static_cast(trailingCommaT); - return GetImpl()->UpdateCallExpression(context, node, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + // auto nn = GetImpl()->UpdateCallExpression(context, node, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + auto nn = GetImpl()->CreateCallExpression(context, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + GetImpl()->AstNodeSetOriginalNode(context, nn, node); + return nn; } KOALA_INTEROP_8(UpdateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean) @@ -710,6 +937,50 @@ KNativePointer impl_CreateFunctionSignature( } KOALA_INTEROP_5(CreateFunctionSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer) +KNativePointer impl_CreateTSUnionType( + KNativePointer contextPtr, + KNativePointerArray typesPtr, + KInt typesLen +) { + auto context = reinterpret_cast(contextPtr); + auto types = reinterpret_cast(typesPtr); + + return GetImpl()->CreateTSUnionType(context, types, typesLen); +} +KOALA_INTEROP_3(CreateTSUnionType, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_TSUnionTypeTypesConst(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()->TSUnionTypeTypesConst(context, node, ¶ms_len); + + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(TSUnionTypeTypesConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateETSUnionTypeIr( + KNativePointer contextPtr, + KNativePointerArray typesPtr, + KInt typesLen +) { + auto context = reinterpret_cast(contextPtr); + auto types = reinterpret_cast(typesPtr); + + return GetImpl()->CreateETSUnionTypeIr(context, types, typesLen); +} +KOALA_INTEROP_3(CreateETSUnionTypeIr, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_ETSUnionTypeIrTypesConst(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()->ETSUnionTypeIrTypesConst(context, node, ¶ms_len); + + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(ETSUnionTypeIrTypesConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_CreateScriptFunction( KNativePointer contextPtr, KNativePointer databodyPtr, @@ -904,6 +1175,31 @@ KNativePointer impl_AstNodeSetParent( } KOALA_INTEROP_3(AstNodeSetParent, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_AstNodeSetOriginalNode( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer originalNodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto originalNode = reinterpret_cast(originalNodePtr); + + GetImpl()->AstNodeSetOriginalNode(context, ast, originalNode); + return ast; +} +KOALA_INTEROP_3(AstNodeSetOriginalNode, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeOriginalNodeConst( + KNativePointer contextPtr, + KNativePointer astPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + + return GetImpl()->AstNodeOriginalNodeConst(context, ast); +} +KOALA_INTEROP_2(AstNodeOriginalNodeConst, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_AstNodeClone( KNativePointer contextPtr, KNativePointer astPtr, @@ -1072,6 +1368,14 @@ KNativePointer impl_UpdateIdentifier2(KNativePointer contextPtr, KNativePointer } KOALA_INTEROP_4(UpdateIdentifier2, KNativePointer, KNativePointer, KNativePointer, KStringPtr, KNativePointer) +KBoolean impl_IdentifierIsPrivateIdentConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->IdentifierIsPrivateIdentConst(context, node); +} +KOALA_INTEROP_2(IdentifierIsPrivateIdentConst, KBoolean, KNativePointer, KNativePointer) + KNativePointer impl_IdentifierSetReference(KNativePointer contextPtr, KNativePointer nodePtr, KBoolean isReferenceK) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -1242,6 +1546,14 @@ KNativePointer impl_VarBinderSetContext(KNativePointer contextPtr) { } KOALA_INTEROP_1(VarBinderSetContext, KNativePointer, KNativePointer) +KNativePointer impl_CreateClassDeclaration(KNativePointer contextPtr, KNativePointer defPtr) { + auto context = reinterpret_cast(contextPtr); + auto def = reinterpret_cast(defPtr); + + return GetImpl()->CreateClassDeclaration(context, def); +} +KOALA_INTEROP_2(CreateClassDeclaration, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_UpdateClassDeclaration(KNativePointer contextPtr, KNativePointer originalPtr, KNativePointer defPtr) { auto context = reinterpret_cast(contextPtr); auto original = reinterpret_cast(originalPtr); @@ -1251,6 +1563,20 @@ KNativePointer impl_UpdateClassDeclaration(KNativePointer contextPtr, KNativePoi } KOALA_INTEROP_3(UpdateClassDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ClassDefinitionSetTypeParams( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointer typeParamsPtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto typeParams = reinterpret_cast(typeParamsPtr); + + GetImpl()->ClassDefinitionSetTypeParams(context, node, typeParams); + return node; +} +KOALA_INTEROP_3(ClassDefinitionSetTypeParams, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_ClassDefinitionLanguageConst( KNativePointer contextPtr, KNativePointer nodePtr @@ -1273,6 +1599,27 @@ KNativePointer impl_ClassDefinitionIdent( } KOALA_INTEROP_2(ClassDefinitionIdent, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_CreateClassDefinition1( + KNativePointer contextPtr, + KNativePointer identPtr, + KNativePointerArray bodyPtr, + KInt bodyLenT, + KInt modifiersT, + KInt flagsT, + KNativePointer langT +) { + auto context = reinterpret_cast(contextPtr); + 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()->CreateClassDefinition1(context, ident, body, bodyLen, modifiers, flags, lang); +} +KOALA_INTEROP_7(CreateClassDefinition1, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KInt, KInt, KNativePointer) + KNativePointer impl_UpdateClassDefinition1( KNativePointer contextPtr, KNativePointer originalPtr, diff --git a/arkoala-arkts/libarkts/package.json b/arkoala-arkts/libarkts/package.json index 42239d8bd8689970e2ef3a30e3963b40514826a9..c910549a16b624506d21d1aa543c9da74ca1fc4b 100644 --- a/arkoala-arkts/libarkts/package.json +++ b/arkoala-arkts/libarkts/package.json @@ -23,7 +23,8 @@ "compile:koala:interop": "cd ../../interop && npm run 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 --reporter-option maxDiffSize=262144", + "test": "npm run compile && backend=es2panda TS_NODE_PROJECT=./test/tsconfig.json mocha -r tsconfig-paths/register --config .mocha.json --reporter-option maxDiffSize=0", + "test:all": "STATE_CHECKED=1 TEST_BIN=1 npm run test", "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", diff --git a/arkoala-arkts/libarkts/src/NativeModule.ts b/arkoala-arkts/libarkts/src/NativeModule.ts index d527d268129f8c21270d7896f2766c1311185a6d..5c7ce76a76b412e1e01a633696813f1184cc2524 100644 --- a/arkoala-arkts/libarkts/src/NativeModule.ts +++ b/arkoala-arkts/libarkts/src/NativeModule.ts @@ -27,7 +27,9 @@ export interface NativeModule { _AstDumperModifierToString(context: KNativePointer, dumper: KNativePointer, flags: KInt): KNativePointer _CreateConfig(argc: number, argv: string[]): KNativePointer + _DestroyConfig(config: KNativePointer): void _CreateContextFromString(config: KNativePointer, source: String, filename: String): KNativePointer + _DestroyContext(context: KNativePointer): void _ProceedToState(context: KNativePointer, state: number): void _ContextProgram(context: KNativePointer): KNativePointer _ProgramAst(program: KNativePointer): KNativePointer @@ -44,12 +46,12 @@ export interface NativeModule { _SourceFileGetChildren(node: KNativePointer): KNativePointer _BlockGetStatements(node: KNativePointer): KNativePointer - _FunctionDeclarationGetIdentifier(node: KNativePointer): KNativePointer - _FunctionDeclarationGetBlock(node: KNativePointer): KNativePointer + _FunctionDeclarationIsAnonymousConst(context: KNativePointer, node: KNativePointer): KBoolean _ExpressionStatementGetExpression(context: KNativePointer, node: KNativePointer): KNativePointer _CallExpressionArguments(context: KNativePointer, node: KNativePointer, returnLen: KNativePointer): KNativePointer _CallExpressionCallee(context: KNativePointer, node: KNativePointer): KNativePointer _IdentifierGetText(node: KNativePointer): KNativePointer + _IdentifierIsPrivateIdentConst(context: KNativePointer, node: KNativePointer): KBoolean _PropertyAccessExpressionGetExpression(node: KNativePointer): KNativePointer _PropertyAccessExpressionGetName(node: KNativePointer): KNativePointer @@ -67,11 +69,14 @@ export interface NativeModule { _ScriptFunctionSetScope(context: KNativePointer, ast: KNativePointer, scope: KNativePointer): KNativePointer _ScriptFunctionDeclareConst(context: KNativePointer, node: KNativePointer): KBoolean _ScriptFunctionFlagsConst(context: KNativePointer, node: KNativePointer): KInt + _ScriptFunctionTypeParams(context: KNativePointer, node: KNativePointer): KNativePointer + _ScriptFunctionReturnTypeAnnotation(context: KNativePointer, node: KNativePointer): KNativePointer _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 + _IdentifierSetName(context: KNativePointer, node: KNativePointer, name: String): 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 @@ -115,7 +120,7 @@ export interface NativeModule { _CreateExpressionStatement(context: KNativePointer, expr: KNativePointer): KNativePointer _UpdateExpressionStatement(context: KNativePointer, node: KNativePointer, expr: KNativePointer): KNativePointer - _CreateETSParameterExpression(context: KNativePointer, identifier: KNativePointer): KNativePointer + _CreateETSParameterExpression(context: KNativePointer, identifier: KNativePointer, initializer: KNativePointer): KNativePointer _CreateETSPrimitiveType(context: KNativePointer, type: KInt): KNativePointer _CreateETSTypeReference(context: KNativePointer, part: KNativePointer): KNativePointer _CreateETSTypeReferencePart(context: KNativePointer, name: KNativePointer, typeParams: KNativePointer, prev: KNativePointer): KNativePointer @@ -123,9 +128,27 @@ export interface NativeModule { _IsIdentifier(node: KNativePointer): KBoolean _IdentifierName(context: KNativePointer, node: KNativePointer): KNativePointer _ETSParameterExpressionIdent(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateTSTypeParameterDeclaration(context: KNativePointer, params: KNativePointerArray, paramsLen: KInt, requiredParams: KInt): KNativePointer + _TSTypeParameterDeclarationParamsConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KInt): KNativePointer + _CreateTSTypeParameter(context: KNativePointer, name: KNativePointer, constraint: KNativePointer, defaultType: KNativePointer): KNativePointer + _TSTypeParameterName(context: KNativePointer, node: KNativePointer): KNativePointer + + _CreateTSUnionType(context: KNativePointer, types: KNativePointerArray, typesLen: KInt): KNativePointer + _TSUnionTypeTypesConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KNativePointer): KNativePointer + _CreateETSUnionTypeIr(context: KNativePointer, types: KNativePointerArray, typesLen: KInt): KNativePointer + _ETSUnionTypeIrTypesConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KNativePointer): KNativePointer + + _CreateVariableDeclaration(context: KNativePointer, kind: KInt, declarators: KNativePointerArray, declaratorsLen: KInt, declare: KBoolean): KNativePointer + _UpdateVariableDeclaration(context: KNativePointer, original: KNativePointer, kind: KInt, declarators: KNativePointerArray, declaratorsLen: KInt, declare: KBoolean): KNativePointer + _CreateVariableDeclarator(context: KNativePointer, flag: KInt, ident: KNativePointer): KNativePointer + _VariableDeclarationDeclaratorsConst(context: KNativePointer, node: KNativePointer): KNativePointer + _VariableDeclaratorId(context: KNativePointer, node: KNativePointer): KNativePointer + _VariableDeclaratorSetInit(context: KNativePointer, node: KNativePointer, init: KNativePointer): void _CreateStringLiteral(context: KNativePointer, string: string): KNativePointer - _StringLiteralString(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateNumberLiteral(context: KNativePointer, string: string): KNativePointer + _NumberLiteralStrConst(context: KNativePointer, node: KNativePointer): KNativePointer + _StringLiteralStrConst(context: KNativePointer, node: KNativePointer): KNativePointer _GetKind(context: KNativePointer, node: KNativePointer): KInt @@ -136,7 +159,11 @@ export interface NativeModule { _ClassDefinitionBody(context: KNativePointer, node: KNativePointer): KNativePointer _ClassDefinitionLanguageConst(context: KNativePointer, node: KNativePointer): KNativePointer _ClassDefinitionIdent(context: KNativePointer, node: KNativePointer): KNativePointer + _ClassDefinitionTypeParamsConst(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateClassDeclaration(context: KNativePointer, def: KNativePointer): KNativePointer _UpdateClassDeclaration(context: KNativePointer, original: KNativePointer, def: KNativePointer): KNativePointer + _CreateClassDefinition1(context: KNativePointer, ident: KNativePointer, body: KNativePointerArray, bodyLen: KInt, modifiers: KInt, flags: KInt, lang: KNativePointer): KNativePointer + _ClassDefinitionSetTypeParams(context: KNativePointer, ast: KNativePointer, typeParams: KNativePointer): void _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 @@ -145,6 +172,8 @@ export interface NativeModule { _AstNodeDumpEtsSrcConst(context: KNativePointer, node: KNativePointer): KNativePointer _AstNodeUpdateChildren(context: KNativePointer, node: KNativePointer): void _AstNodeUpdateAll(context: KNativePointer, node: KNativePointer): void + _AstNodeSetOriginalNode(context: KNativePointer, ast: KNativePointer, originalNode: KNativePointer): void + _AstNodeOriginalNodeConst(context: KNativePointer, ast: KNativePointer): KNativePointer _VarBinderSetProgram(context: KNativePointer): void _VarBinderSetContext(context: KNativePointer): void diff --git a/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts b/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts new file mode 100644 index 0000000000000000000000000000000000000000..72c2f8eacf9add35bc564330cd35d36a127610ed --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts @@ -0,0 +1,88 @@ +/* + * 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 "." +import * as ets from "./typesEts" +import { throwError } from "./utilities" +import { es2pandaKind } from "./enums" + +type arktsKindsType = + | { new (node: ets.Node): arkts.Node } + | { new (node: ets.Identifier): arkts.Identifier } + | { new (node: ets.Program): arkts.SourceFile } + | { new (node: ets.StringLiteral): arkts.StringLiteral } + | { new (node: ets.NumberLiteral): arkts.NumericLiteral } + | { new (node: ets.ExpressionStatement): arkts.ExpressionStatement } + | { new (node: ets.FunctionDeclaration): arkts.FunctionDeclaration } + | { new (node: ets.ReturnStatement): arkts.ReturnStatement } + | { new (node: ets.ETSParameterExpression): arkts.ParameterDeclaration } + | { new (node: ets.CallExpression): arkts.CallExpression } + | { new (node: ets.Block): arkts.Block } + | { new (node: ets.ETSTypeReference): arkts.TypeReferenceNode } + | { new (node: ets.TSTypeParameter): arkts.TypeParameterDeclaration} + | { new (node: ets.MemberExpression): arkts.PropertyAccessExpression} + +export function classByEtsNode(node: ets.Node) { + const kinds = + new Map([ + // [es2pandaKind.UnsupportedNode, ets.UnsupportedNode], + + [es2pandaKind.Program, arkts.SourceFile], + [es2pandaKind.Identifier, arkts.Identifier], + [es2pandaKind.StringLiteral, arkts.StringLiteral], + [es2pandaKind.NumberLiteral, arkts.NumericLiteral], + [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], + [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], + [es2pandaKind.ReturnStatement, arkts.ReturnStatement], + [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], + [es2pandaKind.CallExpression, arkts.CallExpression], + [es2pandaKind.Block, arkts.Block], + [es2pandaKind.ETSTypeReference, arkts.TypeReferenceNode], + [es2pandaKind.TSTypeParameter, arkts.TypeParameterDeclaration], + [es2pandaKind.ETSPrimitiveType, arkts.KeywordTypeNode], + [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], + + // [es2pandaKind.Block, arkts.Block], + // [es2pandaKind.MethodDeclaration, arkts.MethodDeclaration], + // [es2pandaKind.ClassDeclaration, arkts.ClassDeclaration], + // [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], + // [es2pandaKind.PropertyDeclaration, arkts.PropertyDeclaration], + // [es2pandaKind.ETSFunctionType, arkts.FunctionTypeNode], + // [es2pandaKind.CallExpression, arkts.CallExpression], + // [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], + // [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], + // [es2pandaKind.ArrowFunctionExpression, arkts.ArrowFunction], + // [es2pandaKind.ReturnStatement, arkts.ReturnStatement], + // [es2pandaKind.Parameter, arkts.ParameterDeclaration], + // [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], + // [es2pandaKind.NumberLiteral, arkts.NumericLiteral], + // [es2pandaKind.VariableDeclaration, arkts.VariableStatement], + // [es2pandaKind.Program, arkts.SourceFile], + // [es2pandaKind.BinaryExpression, arkts.BinaryExpression], + // [es2pandaKind.VariableDeclarator, arkts.VariableDeclaration], + // [es2pandaKind.TSTypeParameter, arkts.TypeParameterDeclaration], + // [es2pandaKind.ETSPrimitiveType, arkts.ETSPrimitiveType], + // [es2pandaKind.AssignmentExpression, arkts.AssignmentExpression], + // [es2pandaKind.ETSTypeReference, arkts.ETSTypeReference], + // [es2pandaKind.ETSUnionType, arkts.UnionTypeNode], + // [es2pandaKind.ClassDeclaration, ets.UnsupportedNode], + ]) + + return kinds.get(node.kind) ?? throwError('UNSUPPORTED NODE:\n' + arkts.dumpJson(node.peer)) +} + +export function arktsNodeByEtsNode(node: ets.Node): arkts.Node { + return new (classByEtsNode(node))(node as any) +} diff --git a/arkoala-arkts/libarkts/src/arkts/enums.ts b/arkoala-arkts/libarkts/src/arkts/enums.ts index 719dd4d9edf484424ed964f370547b5b987ae23e..81a9df0cb5e09b4bebb8bccbbe12b3c56d7e9c01 100644 --- a/arkoala-arkts/libarkts/src/arkts/enums.ts +++ b/arkoala-arkts/libarkts/src/arkts/enums.ts @@ -39,7 +39,7 @@ export enum es2pandaKind { ClassDeclaration = 5, FunctionDeclaration = 6, PropertyDeclaration = 7, - Parameter = 8, + TSTypeParameterDeclaration = 8, ETSFunctionType = 9, CallExpression = 10, ExpressionStatement = 11, @@ -51,6 +51,18 @@ export enum es2pandaKind { VariableDeclaration = 17, ClassStaticBlock = 18, Program = 19, + BinaryExpression = 20, + FunctionExpression = 21, + ScriptFunction = 22, + VariableDeclarator = 23, + TSTypeParameter = 24, + ETSPrimitiveType = 25, + AssignmentExpression = 26, + ETSTypeReference = 27, + TSUnionType = 28, + ETSUnionType = 29, + ClassDefinition = 30, + ETSTypeReferencePart = 31, }; export enum Es2pandaTokenType { @@ -351,3 +363,61 @@ export enum Es2pandaClassDefinitionModifiers { CLASS_DEFINITION_MODIFIERS_CLASSDEFINITION_CHECKED = 1 << 12, CLASS_DEFINITION_MODIFIERS_DECLARATION_ID_REQUIRED = CLASS_DEFINITION_MODIFIERS_DECLARATION | CLASS_DEFINITION_MODIFIERS_ID_REQUIRED, }; + +export const enum TokenFlags { + None = 0, + /** @internal */ + PrecedingLineBreak = 1 << 0, + /** @internal */ + PrecedingJSDocComment = 1 << 1, + /** @internal */ + Unterminated = 1 << 2, + /** @internal */ + ExtendedUnicodeEscape = 1 << 3, // e.g. `\u{10ffff}` + + Scientific = 1 << 4, // e.g. `10e2` + Octal = 1 << 5, // e.g. `0777` + HexSpecifier = 1 << 6, // e.g. `0x00000000` + BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000` + OctalSpecifier = 1 << 8, // e.g. `0o777` + + /** @internal */ + ContainsSeparator = 1 << 9, // e.g. `0b1100_0101` + /** @internal */ + UnicodeEscape = 1 << 10, // e.g. `\u00a0` + /** @internal */ + ContainsInvalidEscape = 1 << 11, // e.g. `\uhello` + /** @internal */ + HexEscape = 1 << 12, // e.g. `\xa0` + /** @internal */ + ContainsLeadingZero = 1 << 13, // e.g. `0888` + /** @internal */ + ContainsInvalidSeparator = 1 << 14, // e.g. `0_1` + /** @internal */ + PrecedingJSDocLeadingAsterisks = 1 << 15, + /** @internal */ + BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier, + /** @internal */ + WithSpecifier = HexSpecifier | BinaryOrOctalSpecifier, + /** @internal */ + StringLiteralFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, + /** @internal */ + NumericLiteralFlags = Scientific | Octal | ContainsLeadingZero | WithSpecifier | ContainsSeparator | ContainsInvalidSeparator, + /** @internal */ + TemplateLiteralLikeFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, + /** @internal */ + IsInvalid = Octal | ContainsLeadingZero | ContainsInvalidSeparator | ContainsInvalidEscape, +} + +export const enum Es2pandaVariableDeclarationKind { + CONST, + LET, + VAR +} + +export const enum VariableDeclaratorFlag { + LET, + CONST, + VAR, + UNKNOWN, +} diff --git a/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts b/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f56b13bdc7ed2a15cb725fb478eda9019b2ab92 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts @@ -0,0 +1,63 @@ +/* + * 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 "." +import * as ets from "./typesEts" +import global from "./global" +import { KNativePointer } from "@koalaui/interop" +import { nativeModule } from "../NativeModule" +import { throwError } from "./utilities" +import { es2pandaKind } from "./enums" + +export function classByPeer(peer: KNativePointer): { new (peer: KNativePointer): ets.Node } { + const kinds = + new Map([ + // [es2pandaKind.UnsupportedNode, ets.UnsupportedNode], + + [es2pandaKind.Program, ets.Program], + [es2pandaKind.Identifier, ets.Identifier], + [es2pandaKind.StringLiteral, ets.StringLiteral], + [es2pandaKind.NumberLiteral, ets.NumberLiteral], + [es2pandaKind.ExpressionStatement, ets.ExpressionStatement], + [es2pandaKind.FunctionDeclaration, ets.FunctionDeclaration], + [es2pandaKind.ScriptFunction, ets.ScriptFunction], + [es2pandaKind.Block, ets.Block], + [es2pandaKind.ReturnStatement, ets.ReturnStatement], + [es2pandaKind.ETSParameterExpression, ets.ETSParameterExpression], + [es2pandaKind.ETSTypeReference, ets.ETSTypeReference], + [es2pandaKind.TSTypeParameterDeclaration, ets.TSTypeParameterDeclaration], + [es2pandaKind.ETSPrimitiveType, ets.ETSPrimitiveType], + [es2pandaKind.CallExpression, ets.CallExpression], + [es2pandaKind.MemberExpression, ets.MemberExpression], + [es2pandaKind.TSTypeParameter, ets.TSTypeParameter], + ]) + + const kind = nativeModule._GetKind(global.context, peer) + return kinds.get(kind) ?? throwError('UNSUPPORTED NODE:\n' + arkts.dumpJson(peer)) +} + +export function etsNodeByPeer(peer: KNativePointer): T { + if (peer === ets.NULLPTR) { + throwError('peer is NULLPTR') + } + return (new (classByPeer(peer))(peer)) as T +} + +export function etsNodeByPeerNullable(peer: KNativePointer): T | undefined { + if (peer === ets.NULLPTR) { + return undefined + } + return (new (classByPeer(peer))(peer)) as T +} diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts index e8b8c1a1b8bd992a7f36f908c4e3354e2d8a1886..a136f1dca39e84c8cfbe81d4d6870b0529bfae5c 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts @@ -1,3 +1,4 @@ +import global from "../global" import * as ts from "@koalaui/ets-tsc" import { nativeModule } from "../../NativeModule" import { @@ -6,8 +7,9 @@ import { updateScriptFunction, updateChildren, updateNode, + updateModifiers, withString, - withNodeArray, + // withNodeArray, passToken, passScriptFuncModifier, passScriptFuncModifiers, @@ -15,23 +17,31 @@ import { passModifiers, setModifierFlags, getModifierFlags, + // passTypeParams, + // identifierUpdateTypeAnnotation, + passIdentifier, } from "./utilities" import { + passNodeArray, +} from "../utilities" +import { + SyntaxKind, Es2pandaPrimitiveType, Es2pandaMethodDefinitionKind, Es2pandaModifierFlags, Es2pandaScriptFunctionFlags, Es2pandaMemberExpressionKind, Es2pandaClassDefinitionModifiers, + Es2pandaVariableDeclarationKind, + VariableDeclaratorFlag, } from "../enums" import { // util types: - Global, NULLPTR, NULLPTR_ARRAY, // ts types: - ModifierLike, + Modifier, BinaryOperatorToken, Node, @@ -44,113 +54,254 @@ import { PropertyAccessExpression, ParameterDeclaration, ReturnStatement, - IfStatement, + // IfStatement, ExpressionStatement, CallExpression, - ArrowFunction, + // ArrowFunction, TypeReferenceNode, - BinaryExpression, - ClassDeclaration, + // BinaryExpression, + // ClassDeclaration, FunctionTypeNode, TypeNode, Expression, Statement, SourceFile, - ClassElement, - MethodDeclaration, - ConstructorDeclaration, - - // ets types: - ETSPrimitiveType, + // ClassElement, + // MethodDeclaration, + // ConstructorDeclaration, + TypeParameterDeclaration, + NumericLiteral, + // VariableDeclaration, + // VariableDeclarationList, + // VariableStatement, + // UnionTypeNode, } from "../types" -import { dumpModifiers } from "../utilities" +import * as ets from "../typesEts" // TODO: add flags and base export function createNodeFactory() { return { + createSourceFile, + updateSourceFile, createIdentifier, - createIdentifierWithAnnotation, - updateIdentifier, + // updateIdentifier, createStringLiteral, + createNumericLiteral, createFunctionDeclaration, updateFunctionDeclaration, createParameterDeclaration, - createEtsPrimitiveType, + updateParameterDeclaration, createTypeReferenceNode, + updateTypeReferenceNode, createKeywordTypeNode, createBlock, updateBlock, createExpressionStatement, updateExpressionStatement, createReturnStatement, + updateReturnStatement, createPropertyAccessExpression, updatePropertyAccessExpression, createCallExpression, updateCallExpression, - createIfStatement, - createToken, - createBinaryExpression, - createArrowFunction, - updateSourceFile, - updateClassDeclaration, - createFunctionTypeNode, - createMethodDeclaration, - updateMethodDeclaration, - createConstructorDeclaration, + // createIfStatement, + // updateIfStatement, + // createToken, + // createBinaryExpression, + // updateBinaryExpression, + // createArrowFunction, + // updateArrowFunction, + // createClassDeclaration, + // updateClassDeclaration, + // createFunctionTypeNode, + // updateFunctionTypeNode, + // createMethodDeclaration, + // updateMethodDeclaration, + // createConstructorDeclaration, + createTypeParameterDeclaration, + updateTypeParameterDeclaration, + // createVariableDeclarationList, + // updateVariableDeclarationList, + // createVariableStatement, + // updateVariableStatement, + // createVariableDeclaration, + // updateVariableDeclaration, + // createUnionTypeNode, + // updateUnionTypeNode, + } + + // @api + // TODO: + function createSourceFile(source: string): SourceFile { + const node = ets.Program.create(source) + return new SourceFile(node) + } + + // TODO: fix (now doesn't create a new node) + // @api + // updateSourceFile( + // node: SourceFile, + // statements: readonly Statement[], + // isDeclarationFile?: boolean, + // referencedFiles?: readonly FileReference[], + // typeReferences?: readonly FileReference[], + // hasNoDefaultLib?: boolean, + // libReferences?: readonly FileReference[] + // ): SourceFile; + function updateSourceFile( + node: SourceFile, + statements: readonly Statement[] + ): SourceFile { + node._node.statements = passNodeArray(statements) + return new SourceFile(node._node) } // @api // createIdentifier( // text: string // ): Identifier; - function createIdentifier(name: string): Identifier { - const peer = withString(name, (_name: string) => { - return nativeModule._CreateIdentifier1(Global.context, _name) - }) - updateChildren(peer) + function createIdentifier(text: string): Identifier { + const node = ets.Identifier.create(text) + return new Identifier(node) + } - return new Identifier(peer) + // // @api + // // NOT PROVIDED + // function updateIdentifier(node: Identifier, text: string, typeAnnotation?: TypeNode | undefined): Identifier { + // return new Identifier(text, typeAnnotation?.node) + // } + + // @api + // createStringLiteral( + // text: string, + // isSingleQuote?: boolean + // ): StringLiteral; + function createStringLiteral( + str: string + ): StringLiteral { + const node = ets.StringLiteral.create(str) + return new StringLiteral(node) } // @api - // NOT PROVIDED - function createIdentifierWithAnnotation(name: string, typeAnnotation: Node): Identifier { - const peer = withString(name, (_name: string) => { - return nativeModule._CreateIdentifier2(Global.context, _name, typeAnnotation.peer) + // createNumericLiteral( + // value: string | number, + // numericLiteralFlags: TokenFlags = TokenFlags.None + // ): NumericLiteral { + function createNumericLiteral( + str: string + ): NumericLiteral { + const node = ets.NumberLiteral.create(str) + return new NumericLiteral(node) + } +/* + // @api + // createVariableDeclarationList( + // declarations: readonly VariableDeclaration[], + // flags = NodeFlags.None + // ): VariableDeclarationList + function createVariableDeclarationList( + declarations: readonly VariableDeclaration[], + flags = Es2pandaVariableDeclarationKind.CONST + ): VariableDeclarationList { + const peer = withNodeArray(declarations, _declarators => { + return nativeModule._CreateVariableDeclaration(global.context, flags, _declarators, _declarators.length, false) }) - updateChildren(peer) + return new VariableDeclarationList(updateChildren(peer)) + } - return new Identifier(peer) + // @api + // updateVariableDeclarationList( + // node: VariableDeclarationList, + // declarations: readonly VariableDeclaration[] + // ): VariableDeclarationList + function updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[] + ): VariableDeclarationList { + const updated = createVariableDeclarationList(declarations) + return new VariableDeclarationList(updateNode(updated.peer, node.peer)) } - // TODO: remove this method maybe // @api - // NOT PROVIDED - function updateIdentifier(node: Identifier, name: string, typeAnnotation?: TypeNode): Identifier { - const peer = withString(name, (_name: string) => { - return (typeAnnotation === undefined) ? - nativeModule._UpdateIdentifier1(Global.context, node.peer, _name) : - nativeModule._UpdateIdentifier2(Global.context, node.peer, _name, typeAnnotation.peer) + // createVariableStatement( + // modifiers: readonly ModifierLike[] | undefined, + // declarationList: VariableDeclarationList | readonly VariableDeclaration[] + // ): VariableStatement + function createVariableStatement( + modifiers: readonly Modifier[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[] + ): VariableStatement { + const peer = withNodeArray((declarationList instanceof VariableDeclarationList) ? declarationList.declarations : declarationList, _declarators => { + // TODO: fix (const only now) + return nativeModule._CreateVariableDeclaration(global.context, Es2pandaVariableDeclarationKind.CONST, _declarators, _declarators.length, false) }) - updateNode(peer, node.peer) - updateChildren(peer) + // TODO: fix flags + // setModifierFlags(peer, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC | Es2pandaModifierFlags.MODIFIER_FLAGS_CONST) + return new VariableStatement(updateChildren(updateModifiers(peer, modifiers))) + } - return new Identifier(peer) + // @api + // updateVariableStatement( + // node: VariableStatement, + // modifiers: readonly ModifierLike[] | undefined, + // declarationList: VariableDeclarationList + // ): VariableStatement + function updateVariableStatement( + node: VariableStatement, + modifiers: readonly Modifier[] | undefined, + declarationList: VariableDeclarationList + ): VariableStatement { + const updated = createVariableStatement(modifiers, declarationList) + return new VariableStatement(updateNode(updated.peer, updateModifiers(node.peer, modifiers))) } // @api - // createStringLiteral( - // text: string, - // isSingleQuote?: boolean - // ): StringLiteral; - function createStringLiteral(s: string): StringLiteral { - const peer = withString(s, (_s: string) => { - return nativeModule._CreateStringLiteral(Global.context, _s) - }) - updateChildren(peer) + // createVariableDeclaration( + // name: string | BindingName, + // exclamationToken: ExclamationToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined + // ): VariableDeclaration + function createVariableDeclaration( + name: Identifier, + exclamationToken: undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ): VariableDeclaration { + const ident = identifierUpdateTypeAnnotation(name, type) + updateChildren(ident.peer) + // TODO: fix (const only now) + const peer = nativeModule._CreateVariableDeclarator( + global.context, + VariableDeclaratorFlag.CONST, + ident.peer + ) + if (initializer !== undefined) { + nativeModule._VariableDeclaratorSetInit(global.context, peer, initializer.peer) + } + return new VariableDeclaration(updateChildren(peer)) + } - return new StringLiteral(peer) + // @api + // function updateVariableDeclaration( + // node: VariableDeclaration, + // name: BindingName, + // exclamationToken: ExclamationToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined + // ): VariableDeclaration + function updateVariableDeclaration( + node: VariableDeclaration, + name: Identifier, + exclamationToken: undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ): VariableDeclaration { + const updated = createVariableDeclaration(name, exclamationToken, type, initializer) + return new VariableDeclaration(updateNode(updated.peer, node.peer)) } +*/ // @api // createFunctionDeclaration( @@ -163,51 +314,70 @@ export function createNodeFactory() { // body: Block | undefined // ): FunctionDeclaration; function createFunctionDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, - name: string | Identifier, - typeParameters: undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined ): FunctionDeclaration { - const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - type?.peer ?? NULLPTR, - ) - - // TODO: support decl param - const _scriptFunc = createScriptFunction( - body?.peer ?? NULLPTR, - _signature, - (modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), - false, - nativeModule._CreateIdentifier1(_context, _name) - ) - - const _newFuncDecl = - nativeModule._CreateFunctionDeclaration( - _context, - _scriptFunc, - false - ) - setModifierFlags(_newFuncDecl, getModifierFlags(_scriptFunc)) - updateChildren(_newFuncDecl) - - return _newFuncDecl - }) - }) - - return new FunctionDeclaration(peer) + return new FunctionDeclaration( + ets.FunctionDeclaration.create( + ets.ScriptFunction.create( + body?._node, + ets.FunctionSignature.create( + (typeParameters !== undefined) ? + ets.TSTypeParameterDeclaration.create( + passNodeArray(typeParameters) + ) : + undefined, + passNodeArray(parameters), + type?._node + ), + 0, + passModifiers(modifiers) | Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, + body === undefined, + passIdentifier(name) + ), + false + ) + ) + // const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { + // return withNodeArray(parameters, (_parameters: BigUint64Array) => { + // const _context = global.context + + // const _signature = nativeModule._CreateFunctionSignature( + // _context, + // passTypeParams(typeParameters), + // _parameters, + // _parameters.length, + // type?.peer ?? NULLPTR, + // ) + + // const _scriptFunc = createScriptFunction( + // body?.peer ?? NULLPTR, + // _signature, + // passScriptFuncModifiers(modifiers), + // passModifiers(modifiers) | Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, + // body === undefined, + // (name !== undefined) ? nativeModule._CreateIdentifier1(_context, _name) : undefined + // ) + + // const _newFuncDecl = + // nativeModule._CreateFunctionDeclaration( + // _context, + // _scriptFunc, + // false + // ) + // setModifierFlags(_newFuncDecl, getModifierFlags(_scriptFunc)) + + // return _newFuncDecl + // }) + // }) + // return new FunctionDeclaration(updateChildren( + // updateModifiers(peer, [...modifiers ?? [], Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC]) + // )) } // @api @@ -223,63 +393,16 @@ export function createNodeFactory() { // ): FunctionDeclaration; function updateFunctionDeclaration( node: FunctionDeclaration, - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, - name: Identifier, - typeParameters: undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], - type: undefined, + type: TypeNode | undefined, body: Block | undefined ): FunctionDeclaration { - const peer = withString(name.text, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _oldFuncDecl = node.peer - const _oldScriptFunc = nativeModule._FunctionDeclarationFunction( - _context, - _oldFuncDecl - ) - const _oldSignature = nativeModule._ScriptFunctionIrSignature( - _context, - _oldScriptFunc - ) - - const _body = body ? body.peer : NULLPTR - const _signature = nativeModule._CreateFunctionSignature( - _context, - nativeModule._FunctionSignatureTypeParams(_context, _oldSignature), - _parameters, - _parameters.length, - nativeModule._FunctionSignatureReturnType(_context, _oldSignature) - ) - const _scriptFunc = updateScriptFunction( - _oldScriptFunc, - _body, - _signature, - nativeModule._ScriptFunctionFlagsConst(_context, _oldScriptFunc), - nativeModule._AstNodeModifiers(_context, _oldScriptFunc), - false, - nativeModule._UpdateIdentifier1( - _context, - nativeModule._ScriptFunctionId(_context, _oldScriptFunc), - _name - ) - ) - updateNode(_scriptFunc, _oldScriptFunc) - - return nativeModule._UpdateFunctionDeclaration( - _context, - _oldFuncDecl, - _scriptFunc, - false - ) - }) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new FunctionDeclaration(peer) + const updated = createFunctionDeclaration(modifiers, undefined, name, typeParameters, parameters, type, body) + return new FunctionDeclaration(updateNode(updated._node, node._node)) } // @api @@ -292,80 +415,203 @@ export function createNodeFactory() { // initializer?: Expression // ): ParameterDeclaration; function createParameterDeclaration( - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, dotDotDotToken: undefined, - name: Identifier, + name: string | Identifier, questionToken?: undefined, type?: TypeNode, - initializer?: undefined + initializer?: Expression ): ParameterDeclaration { - const peer = nativeModule._CreateETSParameterExpression( - Global.context, - (type === undefined) ? - name.peer : - updateIdentifier( - name, - name.text, - type - ).peer + return new ParameterDeclaration( + ets.ETSParameterExpression.create( + ets.Identifier.create( + (name instanceof Identifier) ? name._node.name : name, + type?._node + ), + initializer?._node + ) ) - updateChildren(peer) - return new ParameterDeclaration(peer) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // name = updateIdentifier( + // name, + // name.text, + // type + // ) + // const peer = nativeModule._CreateETSParameterExpression( + // global.context, + // name.peer, + // initializer?.peer ?? NULLPTR + // ) + // return new ParameterDeclaration(updateChildren(updateModifiers(peer, modifiers))) } - // TODO: maybe remove from api // @api - // NOT PROVIDED - function createEtsPrimitiveType(type: Es2pandaPrimitiveType): TypeNode { - const peer = nativeModule._CreateETSPrimitiveType(Global.context, type) + // function updateParameterDeclaration( + // node: ParameterDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // dotDotDotToken: DotDotDotToken | undefined, + // name: string | BindingName, + // questionToken: QuestionToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined, + // ): ParameterDeclaration + function updateParameterDeclaration( + node: ParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: undefined, + name: string | Identifier, + questionToken?: undefined, + type?: TypeNode, + initializer?: Expression + ): ParameterDeclaration { + const updated = createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer) + return new ParameterDeclaration(updateNode(updated._node, node._node)) + } - return new ETSPrimitiveType(peer) + // @api + // createTypeParameterDeclaration( + // modifiers: readonly Modifier[] | undefined, + // name: string | Identifier, + // constraint?: TypeNode, + // defaultType?: TypeNode + // ): TypeParameterDeclaration; + function createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode + ): TypeParameterDeclaration { + return new TypeParameterDeclaration( + ets.TSTypeParameter.create( + passIdentifier(name), + constraint?._node, + defaultType?._node, + passModifiers(modifiers) + ) + ) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // const peer = nativeModule._CreateTSTypeParameter( + // global.context, + // name.peer, + // constraint?.peer ?? NULLPTR, + // defaultType?.peer ?? NULLPTR + // ) + // return new TypeParameterDeclaration(updateChildren(updateModifiers(peer, modifiers))) } + // @api + // function updateTypeParameterDeclaration( + // node: TypeParameterDeclaration, + // modifiers: readonly Modifier[] | undefined, + // name: Identifier, + // constraint: TypeNode | undefined, + // defaultType: TypeNode | undefined + // ): TypeParameterDeclaration + function updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode + ): TypeParameterDeclaration { + const updated = createTypeParameterDeclaration(modifiers, name, constraint, defaultType) + return new TypeParameterDeclaration(updateNode(updated._node, node._node)) + } +/* + // @api + // createUnionTypeNode( + // types: readonly TypeNode[] + // ): UnionTypeNode + function createUnionTypeNode( + types: readonly TypeNode[] + ): UnionTypeNode { + const peer = withNodeArray(types, (_types: BigUint64Array) => { + return nativeModule._CreateETSUnionTypeIr(global.context, _types, _types.length) + }) + // TODO: rewrite + return new UnionTypeNode(new ets.UnionTypeNode(peer)) + } + + // @api + // function updateUnionTypeNode( + // node: UnionTypeNode, + // types: NodeArray + // ): UnionTypeNode + function updateUnionTypeNode( + node: UnionTypeNode, + types: readonly TypeNode[] + ): UnionTypeNode { + const updated = createUnionTypeNode(types) + return new UnionTypeNode(new ets.UnionTypeNode(updateNode(updated.peer, node.peer))) + } +*/ // @api // createTypeReferenceNode( // typeName: string | EntityName, // typeArguments?: readonly TypeNode[] // ): TypeReferenceNode; - function createTypeReferenceNode(identifier: Identifier, typeArguments?: undefined): TypeReferenceNode { - const typeRefPart = nativeModule._CreateETSTypeReferencePart(Global.context, identifier.peer, NULLPTR, NULLPTR) - updateChildren(typeRefPart) - const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) - updateChildren(peer) + function createTypeReferenceNode( + typeName: Identifier, + typeArguments?: undefined + ): TypeReferenceNode { + return new TypeReferenceNode( + ets.ETSTypeReference.create(typeName._node) + ) + } - return new TypeReferenceNode(peer) + // @api + // function updateTypeReferenceNode( + // node: TypeReferenceNode, + // typeName: EntityName, + // typeArguments: NodeArray | undefined + // ): TypeReferenceNode + function updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: Identifier, + typeArguments?: undefined + ): TypeReferenceNode { + const updated = createTypeReferenceNode(typeName, typeArguments) + return new TypeReferenceNode(updateNode(updated._node, node._node)) } // @internal - function createKeywordTypeNodeFromString(keyword: string): KeywordTypeNode { - const ident = withString(keyword, (name: string) => { - return nativeModule._CreateIdentifier1(Global.context, name) - }) - nativeModule._IdentifierSetReference(Global.context, ident, true) - const typeRefPart = nativeModule._CreateETSTypeReferencePart1(Global.context, ident) - nativeModule._AstNodeSetParent(Global.context, ident, typeRefPart) - const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) - nativeModule._AstNodeSetParent(Global.context, typeRefPart, peer); - - return new KeywordTypeNode(peer) + function createKeywordTypeNodeFromString( + keyword: string + ): KeywordTypeNode { + return new KeywordTypeNode( + ets.ETSTypeReference.create( + ets.Identifier.create(keyword) + ) + ) } // @internal - function createKeywordTypeNodeFromKind(kind: number): KeywordTypeNode { - return new KeywordTypeNode(nativeModule._CreateETSPrimitiveType(Global.context, kind)) + function createKeywordTypeNodeFromKind( + kind: number + ): KeywordTypeNode { + return new KeywordTypeNode( + ets.ETSPrimitiveType.create(kind) + ) } // @api - // createKeywordTypeNode(kind: TKind): KeywordTypeNode; - function createKeywordTypeNode(TKind: ts.KeywordTypeSyntaxKind): KeywordTypeNode { + // createKeywordTypeNode( + // kind: TKind + // ): KeywordTypeNode; + 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) ?? throwError('unsupported keyword') } @@ -374,13 +620,13 @@ export function createNodeFactory() { // statements: readonly Statement[], // multiLine?: boolean // ): Block; - function createBlock(statements: Statement[], multiline?: boolean): Block { - const peer = withNodeArray(statements, (_statements: BigUint64Array) => { - return nativeModule._CreateBlockStatement(Global.context, _statements, _statements.length) - }) - updateChildren(peer) - - return new Block(peer) + function createBlock( + statements: readonly Statement[], + multiline?: boolean + ): Block { + return new Block( + ets.Block.create(passNodeArray(statements)) + ) } // @api @@ -388,76 +634,110 @@ export function createNodeFactory() { // node: Block, // statements: readonly Statement[] // ): Block; - function updateBlock(node: Block, statements: Statement[], multiline?: boolean): Block { - const peer = withNodeArray(statements, (_statements: BigUint64Array) => { - return nativeModule._UpdateBlockStatement(Global.context, node.peer, _statements, _statements.length) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new Block(peer) + function updateBlock( + node: Block, + statements: readonly Statement[] + ): Block { + const updated = createBlock(statements) + return new Block(updateNode(updated._node, node._node)) } // @api - // createExpressionStatement(expression: Expression): ExpressionStatement; - function createExpressionStatement(expression: Expression): ExpressionStatement { - const peer = nativeModule._CreateExpressionStatement(Global.context, expression.peer) - updateChildren(peer) - - return new ExpressionStatement(peer) + // createExpressionStatement( + // expression: Expression + // ): ExpressionStatement; + function createExpressionStatement( + expression: Expression + ): ExpressionStatement { + return new ExpressionStatement( + ets.ExpressionStatement.create(expression._node) + ) } // @api - // updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; - function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement { - const peer = nativeModule._UpdateExpressionStatement(Global.context, node.peer, expression.peer) - updateNode(peer, node.peer) - updateChildren(peer) - - return new ExpressionStatement(peer) + // updateExpressionStatement( + // node: ExpressionStatement, + // expression: Expression + // ): ExpressionStatement; + function updateExpressionStatement( + node: ExpressionStatement, + expression: Expression + ): ExpressionStatement { + const updated = createExpressionStatement(expression) + return new ExpressionStatement(updateNode(updated._node, node._node)) } // @api - // createReturnStatement(expression?: Expression): ReturnStatement; - function createReturnStatement(expression: Expression): ReturnStatement { - const peer = nativeModule._CreateReturnStatement1(Global.context, expression.peer) - updateChildren(peer) + // createReturnStatement( + // expression?: Expression + // ): ReturnStatement; + function createReturnStatement( + expression: Expression + ): ReturnStatement { + return new ReturnStatement( + ets.ReturnStatement.create(expression._node) + ) + } - return new ReturnStatement(peer) + // @api + // function updateReturnStatement( + // node: ReturnStatement, + // expression: Expression | undefined + // ): ReturnStatement + function updateReturnStatement( + node: ReturnStatement, + expression: Expression + ): ReturnStatement { + const updated = createReturnStatement(expression) + return new ReturnStatement(updateNode(updated._node, node._node)) } // @api - // createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; - function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression { - const peer = nativeModule._CreateMemberExpression( - Global.context, - expression.peer, - name.peer, - Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, - false, - false + // createPropertyAccessExpression( + // expression: Expression, + // name: string | MemberName + // ): PropertyAccessExpression; + function createPropertyAccessExpression( + expression: Expression, + name: string | Identifier + ): PropertyAccessExpression { + return new PropertyAccessExpression( + ets.MemberExpression.create( + expression._node, + passIdentifier(name), + Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, + false, + false + ) ) - updateChildren(peer) - return new PropertyAccessExpression(peer) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // const peer = nativeModule._CreateMemberExpression( + // global.context, + // expression.peer, + // name.peer, + // Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, + // false, + // false + // ) + // return new PropertyAccessExpression(updateChildren(peer)) } // @api - // updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: MemberName): PropertyAccessExpression; - function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression { - const peer = nativeModule._UpdateMemberExpression( - Global.context, - node.peer, - expression.peer, - name.peer, - Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, - false, - false - ) - updateNode(peer, node.peer) - updateChildren(peer) - - return new PropertyAccessExpression(peer) + // updatePropertyAccessExpression( + // node: PropertyAccessExpression, + // expression: Expression, + // name: MemberName + // ): PropertyAccessExpression; + function updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: Identifier + ): PropertyAccessExpression { + const updated = createPropertyAccessExpression(expression, name) + return new PropertyAccessExpression(updateNode(updated._node, node._node)) } // @api @@ -468,23 +748,33 @@ export function createNodeFactory() { // ): CallExpression; function createCallExpression( expression: Expression, - typeArguments?: undefined, - argumentsArray?: readonly Expression[] | undefined + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined ): CallExpression { - const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { - return nativeModule._CreateCallExpression( - Global.context, - expression.peer, - _arguments, - _arguments.length, - NULLPTR, - false, - false + return new CallExpression( + ets.CallExpression.create( + expression._node, + (typeArguments !== undefined) ? + ets.TSTypeParameterDeclaration.create( + passNodeArray(typeArguments) + ) : + undefined, + passNodeArray(argumentsArray) ) - }) - updateChildren(peer) - - return new CallExpression(peer) + ) + // const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { + // return nativeModule._CreateCallExpression( + // global.context, + // expression.peer, + // _arguments, + // _arguments.length, + // // TODO: pass typeArgs + // NULLPTR, + // false, + // false + // ) + // }) + // return new CallExpression(updateChildren(peer)) } // @api @@ -497,44 +787,52 @@ export function createNodeFactory() { function updateCallExpression( node: CallExpression, expression: Expression, - typeArguments?: undefined, - argumentsArray?: readonly Expression[] | undefined + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined ): CallExpression { - const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { - return nativeModule._UpdateCallExpression( - Global.context, - node.peer, - expression.peer, - _arguments, - _arguments.length, - NULLPTR, - false, - false - ) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new CallExpression(peer) + const updated = createCallExpression(expression, typeArguments, argumentsArray) + return new CallExpression(updateNode(updated._node, node._node)) } - +/* // @api // createIfStatement( // expression: Expression, // thenStatement: Statement, // elseStatement?: Statement // ): IfStatement; - function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: undefined): IfStatement { - const peer = nativeModule._CreateIfStatement(Global.context, expression.peer, thenStatement.peer, NULLPTR) - updateChildren(peer) + function createIfStatement( + expression: Expression, + thenStatement: Statement, + elseStatement?: undefined + ): IfStatement { + const peer = nativeModule._CreateIfStatement(global.context, expression.peer, thenStatement.peer, NULLPTR) + return new IfStatement(updateChildren(peer)) + } - return new IfStatement(peer) + // @api + // updateIfStatement( + // expression: Expression, + // thenStatement: Statement, + // elseStatement: Statement | undefined + // ): IfStatement; + function updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement?: undefined + ): IfStatement { + const updated = createIfStatement(expression, thenStatement, elseStatement) + return new IfStatement(updateNode(updated.peer, node.peer)) } // TODO: fix maybe (temporary solution) // @api - // createToken(token: SyntaxKind._): _; - function createToken(token: TKind) { + // createToken( + // token: SyntaxKind._ + // ): _; + function createToken( + token: TKind + ) { return new Token(token) } @@ -544,11 +842,30 @@ export function createNodeFactory() { // operator: BinaryOperator | BinaryOperatorToken, // right: Expression // ): BinaryExpression; - function createBinaryExpression(left: Expression, operator: BinaryOperatorToken, right: Expression): BinaryExpression { - const peer = nativeModule._CreateBinaryExpression(Global.context, left.peer, right.peer, passToken(operator)) - updateChildren(peer) + function createBinaryExpression( + left: Expression, + operator: BinaryOperatorToken, + right: Expression + ): BinaryExpression { + const peer = nativeModule._CreateBinaryExpression(global.context, left.peer, right.peer, passToken(operator)) + return new BinaryExpression(updateChildren(peer)) + } - return new BinaryExpression(peer) + // @api + // function updateBinaryExpression( + // node: BinaryExpression, + // left: Expression, + // operator: BinaryOperatorToken, + // right: Expression + // ): BinaryExpression + function updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperatorToken, + right: Expression + ): BinaryExpression { + const updated = createBinaryExpression(left, operator, right) + return new BinaryExpression(updateNode(updated.peer, node.peer)) } // @api @@ -561,7 +878,7 @@ export function createNodeFactory() { // body: ConciseBody // ): ArrowFunction; function createArrowFunction( - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, typeParameters: undefined, parameters: readonly ParameterDeclaration[], type: undefined, @@ -569,7 +886,7 @@ export function createNodeFactory() { body: Block ) { const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _body = body.peer const _signature = nativeModule._CreateFunctionSignature( @@ -597,28 +914,71 @@ export function createNodeFactory() { return _arrowFunc }) + return new ArrowFunction(updateChildren(updateModifiers(peer, modifiers))) + } - return new ArrowFunction(peer) + // @api + // function updateArrowFunction( + // node: ArrowFunction, + // modifiers: readonly Modifier[] | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // parameters: readonly ParameterDeclaration[], + // type: TypeNode | undefined, + // equalsGreaterThanToken: EqualsGreaterThanToken, + // body: ConciseBody, + // ): ArrowFunction + function updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + equalsGreaterThanToken: undefined, + body: Block, + ): ArrowFunction { + const updated = createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body) + return new ArrowFunction(updateNode(updated.peer, node.peer)) } - // TODO: fix (now doesn't create a new node) // @api - // updateSourceFile( - // node: SourceFile, - // statements: readonly Statement[], - // isDeclarationFile?: boolean, - // referencedFiles?: readonly FileReference[], - // typeReferences?: readonly FileReference[], - // hasNoDefaultLib?: boolean, - // libReferences?: readonly FileReference[] - // ): SourceFile; - function updateSourceFile(node: SourceFile, statements: readonly Statement[]): SourceFile { - withNodeArray(statements, (_statements: BigUint64Array) => { - nativeModule._BlockStatementSetStatements(Global.context, node.peer, _statements, _statements.length) - }) - updateChildren(node.peer) + // function createClassDeclaration( + // modifiers: readonly ModifierLike[] | undefined, + // name: string | Identifier | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // heritageClauses: readonly HeritageClause[] | undefined, + // members: readonly ClassElement[], + // ): ClassDeclaration + function createClassDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: undefined, + members: readonly ClassElement[] + ) { + const peer = withNodeArray(members, (_members: BigUint64Array) => { + const _context = global.context - return node + const _newClassDefinition = nativeModule._CreateClassDefinition1( + _context, + // TODO: maybe this is wrong + passIdentifier(name), + _members, + _members.length, + Es2pandaClassDefinitionModifiers.CLASS_DEFINITION_MODIFIERS_NONE, + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, + // TODO: fix lang + NULLPTR + ) + nativeModule._ClassDefinitionSetTypeParams(_context, _newClassDefinition, passTypeParams(typeParameters)) + updateModifiers(_newClassDefinition, modifiers) + updateChildren(_newClassDefinition) + + return nativeModule._CreateClassDeclaration( + _context, + _newClassDefinition + ) + }) + return new ClassDeclaration(updateChildren(updateModifiers(peer, modifiers))) } // @api @@ -632,14 +992,18 @@ export function createNodeFactory() { // ): ClassDeclaration; function updateClassDeclaration( node: ClassDeclaration, - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: undefined, heritageClauses: undefined, members: readonly ClassElement[] ) { + // TODO: rewrite like this (impossible now because of Language param) + // const updated = createClassDeclaration(modifiers, name, typeParameters, heritageClauses, members) + // return new ClassDeclaration(updateNode(updated.peer, node.peer)) + const peer = withNodeArray(members, (_members: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _classDefinition = nativeModule._ClassDeclarationDefinition( _context, @@ -655,15 +1019,16 @@ export function createNodeFactory() { _context, _classDefinition, // TODO: maybe this is wrong - (name === undefined) ? NULLPTR : name.peer, + passIdentifier(name), _members, _members.length, Es2pandaClassDefinitionModifiers.CLASS_DEFINITION_MODIFIERS_NONE, Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, _lang ) + nativeModule._ClassDefinitionSetTypeParams(_context, _newClassDefinition, passTypeParams(typeParameters)) + updateModifiers(_newClassDefinition, modifiers) updateNode(_newClassDefinition, _classDefinition) - updateChildren(_newClassDefinition) return nativeModule._UpdateClassDeclaration( _context, @@ -671,10 +1036,7 @@ export function createNodeFactory() { _newClassDefinition ) }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new ClassDeclaration(peer) + return new ClassDeclaration(updateNode(updateModifiers(peer, modifiers), node.peer)) } // @api @@ -690,7 +1052,7 @@ export function createNodeFactory() { ): FunctionTypeNode { const _signature = withNodeArray(parameters, (_parameters: BigUint64Array) => { return nativeModule._CreateFunctionSignature( - Global.context, + global.context, NULLPTR, _parameters, _parameters.length, @@ -699,13 +1061,28 @@ export function createNodeFactory() { }) const peer = nativeModule._CreateETSFunctionTypeIr( - Global.context, + global.context, _signature, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE ) - updateChildren(peer) + return new FunctionTypeNode(new ets.FunctionTypeNode(updateChildren(peer))) + } - return new FunctionTypeNode(peer) + // @api + // function updateFunctionTypeNode( + // node: FunctionTypeNode, + // typeParameters: NodeArray | undefined, + // parameters: NodeArray, + // type: TypeNode, + // ): FunctionTypeNode + function updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode + ): FunctionTypeNode { + const updated = createFunctionTypeNode(typeParameters, parameters, type) + return new FunctionTypeNode(new ets.FunctionTypeNode(updateNode(updated.peer, node.peer))) } // TODO: fix modifiers @@ -721,7 +1098,7 @@ export function createNodeFactory() { // body: Block | undefined // ): MethodDeclaration; function createMethodDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, name: string | Identifier, questionToken: undefined, @@ -730,47 +1107,44 @@ export function createNodeFactory() { type: TypeNode | undefined, body: Block | undefined ): MethodDeclaration { - const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - type?.peer ?? NULLPTR, - ) - - const _ident = nativeModule._CreateIdentifier1(_context, _name) - const _scriptFunc = createScriptFunction( - body?.peer ?? NULLPTR, - _signature, - (modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - (modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, - false, - _ident - ) - - const _funcExpr = nativeModule._CreateFunctionExpression( - Global.context, - _scriptFunc - ) - updateChildren(_funcExpr) - - return nativeModule._CreateMethodDefinition( - _context, - Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, - _ident, - _funcExpr, - (modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, - false - ) - }) - }) - updateChildren(peer) + const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { + const _context = global.context - return new MethodDeclaration(peer) + const _signature = nativeModule._CreateFunctionSignature( + _context, + NULLPTR, + _parameters, + _parameters.length, + type?.peer ?? NULLPTR, + ) + + const _ident = passIdentifier(name) + + const _scriptFunc = createScriptFunction( + body?.peer ?? NULLPTR, + _signature, + passScriptFuncModifiers(modifiers), + passModifiers(modifiers), + false, + _ident + ) + + const _funcExpr = nativeModule._CreateFunctionExpression( + global.context, + _scriptFunc + ) + updateChildren(_funcExpr) + + return nativeModule._CreateMethodDefinition( + _context, + Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, + _ident, + _funcExpr, + passModifiers(modifiers), + false + ) + }) + return new MethodDeclaration(updateChildren(updateModifiers(peer, modifiers))) } // @api @@ -794,58 +1168,21 @@ export function createNodeFactory() { typeParameters: undefined, parameters: readonly ParameterDeclaration[], type: undefined, - body: Block + body: Block | undefined ): MethodDeclaration { - const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _oldFuncExpr = nativeModule._MethodDefinitionFunction(_context, node.peer) - const _oldScriptFunc = nativeModule._ArrowFunctionExpressionFunction(_context, _oldFuncExpr) - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - NULLPTR - ) - - const _scriptFunc = updateScriptFunction( - _oldScriptFunc, - body.peer, - _signature, - // TODO: fix this - // nativeModule._ScriptFunctionFlagsConst(_context, _oldScriptFunc), - Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - nativeModule._AstNodeModifiers(_context, _oldScriptFunc), - false, - name.peer - ) - - const _funcExpr = nativeModule._UpdateFunctionExpression( - Global.context, - _oldFuncExpr, - _scriptFunc - ) - updateChildren(_funcExpr) - - return nativeModule._UpdateMethodDefinition( - Global.context, - node.peer, - nativeModule._MethodDefinitionKindConst(_context, node.peer), - name.peer, - _funcExpr, - nativeModule._AstNodeModifiers(_context, node.peer), - false - ) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new MethodDeclaration(peer) + const updated = createMethodDeclaration( + modifiers, + asteriskToken, + name, + questionToken, + typeParameters, + parameters, + type, + body + ) + return new MethodDeclaration(updateNode(updated.peer, node.peer)) } - // TODO: fix modifiers // @api // createConstructorDeclaration( // modifiers: readonly ModifierLike[] | undefined, @@ -853,12 +1190,12 @@ export function createNodeFactory() { // body: Block | undefined // ): ConstructorDeclaration; function createConstructorDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined ): ConstructorDeclaration { const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _signature = nativeModule._CreateFunctionSignature( _context, @@ -874,15 +1211,15 @@ export function createNodeFactory() { body?.peer ?? NULLPTR, _signature, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE), + passScriptFuncModifiers(modifiers), Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), + passModifiers(modifiers), false, _ident ) const _funcExpr = nativeModule._CreateFunctionExpression( - Global.context, + global.context, _scriptFunc ) updateChildren(_funcExpr) @@ -893,14 +1230,30 @@ export function createNodeFactory() { _ident, _funcExpr, Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), + passModifiers(modifiers), false ) }) - updateChildren(peer) + return new ConstructorDeclaration(updateChildren(updateModifiers(peer, [...modifiers ?? [], Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR]))) + } - return new ConstructorDeclaration(peer) + // @api + // function updateConstructorDeclaration( + // node: ConstructorDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // parameters: readonly ParameterDeclaration[], + // body: Block | undefined, + // ): ConstructorDeclaration + function updateConstructorDeclaration( + node: ConstructorDeclaration, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ): ConstructorDeclaration { + const updated = createConstructorDeclaration(modifiers, parameters, body) + return new ConstructorDeclaration(updateNode(updated.peer, node.peer)) } +*/ } export const factory = createNodeFactory(); diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts index 2afce8fa4213cf28509b839065fdecbbb89605dc..5e1fe28c64da37ea2c4e3c866065a5683dc0fce7 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts @@ -9,24 +9,33 @@ import { FunctionDeclaration, Block, KeywordTypeNode, - PropertyAccessExpression, + // PropertyAccessExpression, ParameterDeclaration, ReturnStatement, - IfStatement, + // IfStatement, ExpressionStatement, CallExpression, - ArrowFunction, + // ArrowFunction, TypeReferenceNode, - BinaryExpression, + // BinaryExpression, BinaryOperatorToken, - ClassDeclaration, + // ClassDeclaration, FunctionTypeNode, TypeNode, Expression, Statement, SourceFile, - ClassElement, - MethodDeclaration, + // ClassElement, + // MethodDeclaration, + // FunctionExpression, + // VariableDeclaration, + // VariableDeclarationList, + // PropertyDeclaration, + // PropertySignature, + // MethodSignature, + // GetAccessorDeclaration, + // SetAccessorDeclaration, + // VariableStatement, } from "../types" export function isIdentifier(node: Node): node is Identifier { @@ -37,17 +46,17 @@ 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 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 -} +// export function isMethodDeclaration(node: Node): node is MethodDeclaration { +// return node.kind === SyntaxKind.MethodDeclaration +// } export function isSourceFile(node: Node): node is SourceFile { return node.kind === SyntaxKind.SourceFile @@ -57,10 +66,58 @@ export function isExpressionStatement(node: Node): node is ExpressionStatement { return node.kind === SyntaxKind.ExpressionStatement } -export function isArrowFunction(node: Node): node is ArrowFunction { - return node.kind === SyntaxKind.ArrowFunction +// export function isArrowFunction(node: Node): node is ArrowFunction { +// return node.kind === SyntaxKind.ArrowFunction +// } + +// export function isClassDeclaration(node: Node): node is ClassDeclaration { +// return node.kind === SyntaxKind.ClassDeclaration +// } + +export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block } -export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node.kind === SyntaxKind.ClassDeclaration +// export function isFunctionExpression(node: Node): node is FunctionExpression { +// return node.kind === SyntaxKind.FunctionExpression +// } + +export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter } + +// export function isVariableDeclaration(node: Node): node is VariableDeclaration { +// return node.kind === SyntaxKind.VariableDeclaration +// } + +// export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { +// return node.kind === SyntaxKind.VariableDeclarationList +// } + +// export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { +// return node.kind === SyntaxKind.PropertyDeclaration +// } + +// export function isPropertySignature(node: Node): node is PropertySignature { +// return node.kind === SyntaxKind.PropertySignature +// } + +export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { + return node.kind === SyntaxKind.FunctionType +} + +// export function isMethodSignature(node: Node): node is MethodSignature { +// return node.kind === SyntaxKind.MethodSignature +// } + +// export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { +// return node.kind === SyntaxKind.GetAccessor +// } + +// export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { +// return node.kind === SyntaxKind.SetAccessor +// } + +// export function isVariableStatement(node: Node): node is VariableStatement { +// return node.kind === SyntaxKind.VariableStatement +// } diff --git a/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts b/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts index 49f9f110224284a5d7f4b8158586242f68082d9a..2966c7fc591a16db2a77b96913aa85bdc87d8f10 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts @@ -15,41 +15,77 @@ import { nativeModule } from "../../NativeModule" import { KNativePointer, KInt, KBoolean } from "@koalaui/interop" -import * as arkts from "../types" +import * as arkts from "../." +import * as ets from "../typesEts" +import global from "../global" import { - SyntaxKind, TokenSyntaxKind, Es2pandaModifierFlags, Es2pandaScriptFunctionFlags, - Es2pandaTokenType, } from "../enums" -import { throwError } from "../utilities" +import { + throwError, + packModifiers, +} from "../utilities" + export { throwError } from "../utilities" export function setParent(node: KNativePointer, parent: KNativePointer) { - nativeModule._AstNodeSetParent(arkts.Global.context, node, parent) + nativeModule._AstNodeSetParent(global.context, node, parent) } export function getModifierFlags(node: KNativePointer): KInt { - return nativeModule._AstNodeModifiers(arkts.Global.context, node) + return nativeModule._AstNodeModifiers(global.context, node) } export function setModifierFlags(node: KNativePointer, flags: KInt) { - nativeModule._AstNodeClearModifier(arkts.Global.context, node, arkts.ALL_FLAGS) - nativeModule._AstNodeAddModifier(arkts.Global.context, node, flags) + nativeModule._AstNodeClearModifier(global.context, node, arkts.ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, node, flags) } export function updateAllChildren(peer: KNativePointer) { - nativeModule._AstNodeUpdateAll(arkts.Global.context, peer) + nativeModule._AstNodeUpdateAll(global.context, peer) } -export function updateChildren(peer: KNativePointer) { - nativeModule._AstNodeUpdateChildren(arkts.Global.context, peer) +export function updateChildren(peer: KNativePointer): KNativePointer { + if (peer === arkts.NULLPTR) { + throwError('updateChildren called on NULLPTR') + } + nativeModule._AstNodeUpdateChildren(global.context, peer) + return peer } // TODO: update scopes and other data -export function updateNode(peer: KNativePointer, original: KNativePointer) { - setModifierFlags(peer, getModifierFlags(original)) +export function updateNode(node: T, original: T): T { + if (node.peer === arkts.NULLPTR) { + throwError('updateNode called on NULLPTR') + } + nativeModule._AstNodeSetOriginalNode(global.context, node.peer, original.peer) + nativeModule._AstNodeSetParent(global.context, node.peer, nativeModule._AstNodeParent(global.context, original.peer)) + nativeModule._AstNodeUpdateChildren(global.context, node.peer) + setModifierFlags(node.peer, getModifierFlags(original.peer)) + // new flags may change children + updateChildren(node.peer) + // switch (classByPeer(peer)) { + // case arkts.ClassDeclaration: { + // // TODO: update Language + // break + // } + // } + return node +} + +export function updateNodeModifiers(node: T, modifiers: ReadonlyArray | undefined): T { + // node.modifiers = modifiers + return node +} + +export function updateModifiers(peer: KNativePointer, modifiers: ReadonlyArray | undefined): KNativePointer { + if (modifiers === undefined) { + return peer + } + setModifierFlags(peer, packModifiers(modifiers)) + return peer } export function createScriptFunction( @@ -63,7 +99,7 @@ export function createScriptFunction( ident: KNativePointer | undefined ): KNativePointer { const peer = nativeModule._CreateScriptFunction( - arkts.Global.context, + global.context, body, signature, functionFlags, @@ -71,7 +107,7 @@ export function createScriptFunction( declare ) if (ident !== undefined) { - nativeModule._ScriptFunctionSetIdent(arkts.Global.context, peer, ident) + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident) } updateChildren(peer) return peer @@ -89,7 +125,7 @@ export function updateScriptFunction( ident: KNativePointer | undefined ): KNativePointer { const peer = nativeModule._UpdateScriptFunction( - arkts.Global.context, + global.context, original, body, signature, @@ -98,7 +134,7 @@ export function updateScriptFunction( declare ) if (ident !== undefined) { - nativeModule._ScriptFunctionSetIdent(arkts.Global.context, peer, ident) + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident) } updateChildren(peer) return peer @@ -111,85 +147,72 @@ export function withString( return exec(data ?? "") } -export function withNodeArray( - data: readonly arkts.Node[] | undefined, - exec: (nodes: BigUint64Array) => TOut -): TOut { - const _data = new BigUint64Array((data === undefined) ? [] : data.map(node => BigInt(node.peer))) - return exec(_data) -} - -// TODO: rewrite this maybe -class Global { - private static _tokenKinds?: Map - - public static get tokenKinds(): Map { - if (this._tokenKinds === undefined) { - this._tokenKinds = - new Map([ - [SyntaxKind.PlusToken, Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_PLUS], - ]) - } - return this._tokenKinds +// export function withNodeArray( +// data: readonly arkts.Node[] | undefined, +// exec: (nodes: BigUint64Array) => TOut +// ): TOut { +// if ((data !== undefined) && data.map(node => node.peer).includes(arkts.NULLPTR)) { +// throwError('trying to pass NULLPTR in function withNodeArray') +// } +// const _data = new BigUint64Array((data === undefined) ? [] : data.map(node => BigInt(node.peer))) +// return exec(_data) +// } + +export function passIdentifier(node: arkts.Identifier | string): ets.Identifier +export function passIdentifier(node: arkts.Identifier | string | undefined): ets.Identifier | undefined +export function passIdentifier(node: arkts.Identifier | string | undefined): ets.Identifier | undefined { + if (node === undefined) { + return undefined } - - private static _scriptFunctionFlags?: Map - - public static get scriptFunctionFlags(): Map { - if (this._scriptFunctionFlags === undefined) { - this._scriptFunctionFlags = - new Map([ - [SyntaxKind.StaticKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_STATIC_BLOCK], - [SyntaxKind.AsyncKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ASYNC], - [SyntaxKind.PublicKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE], - ]) - } - return this._scriptFunctionFlags - } - - private static _modifierFlags?: Map - - public static get modifierFlags(): Map { - if (this._modifierFlags === undefined) { - this._modifierFlags = - new Map([ - [SyntaxKind.StaticKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC], - [SyntaxKind.AsyncKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC], - [SyntaxKind.PublicKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC], - ]) - } - return this._modifierFlags + if (node instanceof arkts.Identifier) { + return node._node } + return ets.Identifier.create(node) } export function passToken(token: arkts.Token): KInt { - return Global.tokenKinds.get(token.kind) ?? throwError('unsupported token') + return global.tokenKinds.get(token.kind) ?? throwError('unsupported token') } -export function passScriptFuncModifier(modifierToken: arkts.ModifierLike) { - return Global.scriptFunctionFlags.get(modifierToken.kind) ?? throwError('unsupported ScriptFunction flag') +export function passScriptFuncModifier(modifierToken: arkts.Modifier): Es2pandaScriptFunctionFlags { + return global.scriptFunctionFlags.get(modifierToken.kind) ?? throwError(`Unsupported ScriptFunction flag: ${modifierToken.kind}`) } -export function passScriptFuncModifiers(modifiers: readonly arkts.ModifierLike[]): KInt { - let flags = Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE - - modifiers.forEach(flag => { - flags = flags | passScriptFuncModifier(flag) - }) +export function passScriptFuncModifiers(modifiers: readonly arkts.Modifier[] | undefined): KInt { + return modifiers?.reduce( + (prev, curr) => prev | passScriptFuncModifier(curr), + Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE + ) ?? Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE +} - return flags +export function passModifier(modifierToken: arkts.Modifier): Es2pandaModifierFlags { + return global.modifierFlags.get(modifierToken.kind) ?? throwError(`Unsupported Modifier flag: ${modifierToken.kind}`) } -export function passModifier(modifierToken: arkts.ModifierLike) { - return Global.modifierFlags.get(modifierToken.kind) ?? throwError('unsupported Modifier flag') +export function passModifiers(modifiers: readonly arkts.Modifier[] | undefined): KInt { + return modifiers?.reduce( + (prev, curr) => prev | passModifier(curr), + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + ) ?? Es2pandaModifierFlags.MODIFIER_FLAGS_NONE } -export function passModifiers(modifiers: readonly arkts.ModifierLike[]): KInt { - let flags = Es2pandaModifierFlags.MODIFIER_FLAGS_NONE +// // TODO: support unrequired params (with ?) +// export function passTypeParams(params: readonly arkts.TypeParameterDeclaration[] | undefined): KNativePointer { +// if (params === undefined) { +// return arkts.NULLPTR +// } - modifiers.forEach(flag => { - flags = flags | passModifier(flag) - }) +// const peer = withNodeArray(params, (_params: BigUint64Array) => { +// return nativeModule._CreateTSTypeParameterDeclaration(global.context, _params, _params.length, _params.length) +// }) +// updateChildren(peer) - return flags -} +// return peer +// } + +// export function identifierUpdateTypeAnnotation(node: arkts.Identifier, type: arkts.TypeNode | undefined): arkts.Identifier { +// const peer = withString(node.text, (_text: string) => { +// return nativeModule._UpdateIdentifier2(global.context, node.peer, _text, type?.peer ?? arkts.NULLPTR) +// }) +// return new arkts.Identifier(node.text, type?.node) +// } diff --git a/arkoala-arkts/libarkts/src/arkts/global.ts b/arkoala-arkts/libarkts/src/arkts/global.ts new file mode 100644 index 0000000000000000000000000000000000000000..83d093a316a679c92016dc30aee114f279e3a13c --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/global.ts @@ -0,0 +1,132 @@ +import { KNativePointer } from "@koalaui/interop" +import { + SyntaxKind, + es2pandaKind, + TokenSyntaxKind, + Es2pandaScriptFunctionFlags, + Es2pandaTokenType, + Es2pandaModifierFlags, +} from "./enums" +import * as util from "./utilities" +import * as arkts from "./types" +import * as ets from "./typesEts" + +// TODO: idk how to write +// type ModifierKinds = arkts.ModifierSyntaxKind | SyntaxKind.UnknownKeyword | SyntaxKind.ConstructorKeyword + +export default 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) + } + + private static _tokenKinds?: Map + + public static get tokenKinds(): Map { + if (this._tokenKinds === undefined) { + this._tokenKinds = + new Map([ + [SyntaxKind.PlusToken, Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_PLUS], + ]) + } + return this._tokenKinds + } + + private static _scriptFunctionFlags?: Map + + public static get scriptFunctionFlags(): Map { + if (this._scriptFunctionFlags === undefined) { + this._scriptFunctionFlags = + new Map([ + [SyntaxKind.StaticKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_STATIC_BLOCK], + [SyntaxKind.AsyncKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ASYNC], + [SyntaxKind.PublicKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE], + ]) + } + return this._scriptFunctionFlags + } + + private static _modifierFlags?: Map + + public static get modifierFlags(): Map { + if (this._modifierFlags === undefined) { + this._modifierFlags = + new Map([ + // [SyntaxKind.UnknownKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_NONE], + // [SyntaxKind.ConstructorKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR], + + [SyntaxKind.AbstractKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ABSTRACT], + // TODO: unsupported + // [SyntaxKind.AccessorKeyword, Es2pandaModifierFlags.], + [SyntaxKind.AsyncKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC], + [SyntaxKind.ConstKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_CONST], + [SyntaxKind.DeclareKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE], + [SyntaxKind.DefaultKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT], + [SyntaxKind.ExportKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_EXPORT], + [SyntaxKind.InKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_IN], + [SyntaxKind.PrivateKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE], + [SyntaxKind.ProtectedKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED], + [SyntaxKind.PublicKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC], + [SyntaxKind.OutKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_OUT], + [SyntaxKind.OverrideKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_OVERRIDE], + [SyntaxKind.ReadonlyKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_READONLY], + [SyntaxKind.StaticKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC], + ]) + } + return this._modifierFlags + } + + private static _translateModifiers?: Map + + public static get translateModifiers(): Map { + if (this._translateModifiers === undefined) { + this._translateModifiers = + new Map([ + // [Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, SyntaxKind.UnknownKeyword], + // [Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR, SyntaxKind.ConstructorKeyword], + + [Es2pandaModifierFlags.MODIFIER_FLAGS_ABSTRACT, SyntaxKind.AbstractKeyword], + // TODO: unsupported + // [Es2pandaModifierFlags. , SyntaxKind.AccessorKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC, SyntaxKind.AsyncKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_CONST, SyntaxKind.ConstKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE, SyntaxKind.DeclareKeyword], + // TODO: choose one + // [Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT, SyntaxKind.DefaultClause], + // [Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT, SyntaxKind.DefaultKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_EXPORT, SyntaxKind.ExportKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_IN, SyntaxKind.InKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE, SyntaxKind.PrivateKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED, SyntaxKind.ProtectedKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC, SyntaxKind.PublicKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_OUT, SyntaxKind.OutKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_OVERRIDE, SyntaxKind.OverrideKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_READONLY, SyntaxKind.ReadonlyKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, SyntaxKind.StaticKeyword], + ]) + } + return this._translateModifiers + } +} diff --git a/arkoala-arkts/libarkts/src/arkts/index.ts b/arkoala-arkts/libarkts/src/arkts/index.ts index 4ee61c3be35095383507b2b9aef75517433e611c..97b5747104134962038a14a54b88587eb169e7d9 100644 --- a/arkoala-arkts/libarkts/src/arkts/index.ts +++ b/arkoala-arkts/libarkts/src/arkts/index.ts @@ -19,9 +19,10 @@ export * from "./utilitiesPublic" export * from "./utilities" export * from "./factory/nodeFactory" export * from "./factory/nodeTests" -export { - visitEachChild, -} from "./visitor" +export * from "./global" +// export { +// visitEachChild, +// } from "./visitor" export { SyntaxKind, ContextState, diff --git a/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts b/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts deleted file mode 100644 index fbda61f6028d291455ea3239c6660c6364550e52..0000000000000000000000000000000000000000 --- a/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts +++ /dev/null @@ -1,57 +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 arkts from "./types" -import { KNativePointer } from "@koalaui/interop" -import { es2pandaKind } from "./enums" -import { nativeModule } from "../NativeModule" - -// TODO: rewrite this maybe -class Global { - private static _kinds?: Map - - public static get kinds(): Map { - if (this._kinds === undefined) { - this._kinds = - new Map([ - [es2pandaKind.Identifier, arkts.Identifier], - [es2pandaKind.StringLiteral, arkts.StringLiteral], - [es2pandaKind.Block, arkts.Block], - [es2pandaKind.MethodDeclaration, arkts.MethodDeclaration], - [es2pandaKind.ClassDeclaration, arkts.ClassDeclaration], - [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], - [es2pandaKind.PropertyDeclaration, arkts.PropertyDeclaration], - [es2pandaKind.ETSFunctionType, arkts.FunctionTypeNode], - [es2pandaKind.CallExpression, arkts.CallExpression], - [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], - [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], - [es2pandaKind.ArrowFunctionExpression, arkts.ArrowFunction], - [es2pandaKind.ReturnStatement, arkts.ReturnStatement], - [es2pandaKind.Parameter, arkts.ParameterDeclaration], - [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], - [es2pandaKind.NumberLiteral, arkts.NumericLiteral], - [es2pandaKind.VariableDeclaration, arkts.VariableStatement], - [es2pandaKind.Program, arkts.SourceFile], - ]) - } - return this._kinds - } -} - -// TODO: maybe rewrite to (new Node(peer)) -export function nodeByPeer(peer: KNativePointer): arkts.Node { - const kind = nativeModule._GetKind(arkts.Global.context, peer) - return new (Global.kinds.get(kind) ?? arkts.UnsupportedNode)(peer) -} diff --git a/arkoala-arkts/libarkts/src/arkts/types.ts b/arkoala-arkts/libarkts/src/arkts/types.ts index 864f51ef396750d94dd0a9929d2c4f9172fd0c45..e8211d42967982f05fc9938a93a9e82a08782645 100644 --- a/arkoala-arkts/libarkts/src/arkts/types.ts +++ b/arkoala-arkts/libarkts/src/arkts/types.ts @@ -2,26 +2,39 @@ import * as ts from "@koalaui/ets-tsc" import { nativeModule } from "../NativeModule" import { KInt, KNativePointer, withStringResult } from "@koalaui/interop" -import * as util from "./utilities" -import { todo } from "./utilities" +// import * as util from "./utilities" +import { + todo, + passEtsNode, + passString, + unpackNodeArray, + unpackNode, + unpackNullableNode, + arktsNodeByEtsNode, + throwError, +} from "./utilities" +import { factory } from "./factory/nodeFactory" +import global from "./global" +import * as ets from "./typesEts" import { Es2pandaModifierFlags, - Es2pandaTokenType, + SyntaxKind, } from "./enums" export const NULLPTR: KNativePointer = BigInt(0) export const NULLPTR_ARRAY = new BigUint64Array([NULLPTR]) +export const EMPTY_MODIFIERS = [] as ReadonlyArray as NodeArray + export const UNSUPPORTED_KIND = 0 -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 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 + ) // TODO: write implementation export interface TransformationContext {} @@ -29,66 +42,51 @@ export interface TransformationContext {} // TODO: write implementation export interface Program {} -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) - } -} - export type NodeArray = ts.NodeArray +// TODO: should be interface export abstract class Node implements ts.Node { - peer: KNativePointer + // peer: KNativePointer = NULLPTR + + // abstract readonly node: ets.Node + + // get parent(): Node { + // const _parent = nativeModule._AstNodeParent(global.context, this.peer) + // if (_parent === NULLPTR) { + // util.throwError('BAD ACCESS: PARENT IS NULLPTR') + // } + // return util.nodeByPeer(_parent) + // } + + // set parent(node: Node) { + // nativeModule._AstNodeSetParent(global.context, this.peer, node.peer) + // } + + // private _modifiers?: KInt + parent: any + + readonly _node?: ets.Node + + // get modifiers(): NodeArray { + // if (this._modifiers === undefined) { + // this._modifiers = nativeModule._AstNodeModifiers(global.context, this.peer) + // } + // // TODO: rewrite + // return util.unpackModifiers(this._modifiers) as NodeArray + // } + + // set modifiers(flags: ReadonlyArray | undefined) { + // nativeModule._AstNodeClearModifier(global.context, this.peer, ALL_FLAGS) + // this._modifiers = flags + // if (flags === undefined) { + // return + // } + // nativeModule._AstNodeAddModifier(global.context, this.peer, util.packModifiers(this._modifiers)) + // } + + abstract kind: SyntaxKind - protected constructor(peer: KNativePointer) { - this.peer = peer - } - - get parent(): Node { - return util.nodeByPeer(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 + // TODO: support minimal interface 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.") } @@ -105,23 +103,23 @@ export abstract class Node implements ts.Node { 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 } // TODO: add all tokens export type BinaryOperator = | ts.SyntaxKind.PlusToken + | ts.SyntaxKind.MinusToken export type BinaryOperatorToken = Token; // TODO: rethink maybe (temporary solution) -export class Token { +export class Token extends Node { constructor(kind: TKind) { + super() this.kind = kind } @@ -129,107 +127,151 @@ export class Token { } export type ModifierSyntaxKind = - | ts.SyntaxKind.AbstractKeyword - | ts.SyntaxKind.AccessorKeyword - | ts.SyntaxKind.AsyncKeyword - | ts.SyntaxKind.ConstKeyword - | ts.SyntaxKind.DeclareKeyword - | ts.SyntaxKind.DefaultKeyword - | ts.SyntaxKind.ExportKeyword - | ts.SyntaxKind.InKeyword - | ts.SyntaxKind.PrivateKeyword - | ts.SyntaxKind.ProtectedKeyword - | ts.SyntaxKind.PublicKeyword - | ts.SyntaxKind.ReadonlyKeyword - | ts.SyntaxKind.OutKeyword - | ts.SyntaxKind.OverrideKeyword - | ts.SyntaxKind.StaticKeyword; - -// TODO: rethink maybe (temporary solution) -export class ModifierToken extends Token { - constructor(kind: TKind) { - super(kind) + // | SyntaxKind.ConstructorKeyword + | SyntaxKind.AbstractKeyword + | SyntaxKind.AccessorKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.OutKeyword + | SyntaxKind.OverrideKeyword + | SyntaxKind.StaticKeyword; + +export class Modifier extends Node { + constructor(kind: ModifierSyntaxKind) { + super() this.kind = kind } - readonly kind: TKind; + public toString(): string { + return `${global.modifierFlags.get(this.kind)}` + } + + kind: ModifierSyntaxKind } -export type AbstractKeyword = ModifierToken; -export type AccessorKeyword = ModifierToken; -export type AsyncKeyword = ModifierToken; -export type ConstKeyword = ModifierToken; -export type DeclareKeyword = ModifierToken; -export type DefaultKeyword = ModifierToken; -export type ExportKeyword = ModifierToken; -export type InKeyword = ModifierToken; -export type PrivateKeyword = ModifierToken; -export type ProtectedKeyword = ModifierToken; -export type PublicKeyword = ModifierToken; -export type ReadonlyKeyword = ModifierToken; -export type OutKeyword = ModifierToken; -export type OverrideKeyword = ModifierToken; -export type StaticKeyword = ModifierToken; - -export type Modifier = - | AbstractKeyword - | AccessorKeyword - | AsyncKeyword - | ConstKeyword - | DeclareKeyword - | DefaultKeyword - | ExportKeyword - | InKeyword - | PrivateKeyword - | ProtectedKeyword - | PublicKeyword - | OutKeyword - | OverrideKeyword - | ReadonlyKeyword - | StaticKeyword; - -// export type ModifierLike = Modifier | Decorator; -export type ModifierLike = Modifier; +// export class FunctionDeclaration extends Node implements ts.FunctionDeclaration, FunctionLikeDeclarationBase { +export class FunctionDeclaration extends Node implements ts.FunctionDeclaration { + constructor(_node: ets.FunctionDeclaration) { + super() + this._node = _node + this.name = unpackNode(this._node.name) + this.body = unpackNode(this._node.body) + this.typeParameters = unpackNodeArray(this._node.typeParamsDecl?.parameters) + this.type = unpackNode(this._node.type) + this.parameters = unpackNodeArray(this._node.parameters) + } -export class FunctionDeclaration extends Node implements ts.FunctionDeclaration { + readonly _node: ets.FunctionDeclaration + + readonly name?: Identifier | undefined + readonly body?: Block | undefined + readonly typeParameters?: NodeArray | undefined; + readonly type?: TypeNode | undefined + readonly parameters: NodeArray + readonly kind: ts.SyntaxKind.FunctionDeclaration = ts.SyntaxKind.FunctionDeclaration + + // TODO: support minimal interface + asteriskToken?: ts.AsteriskToken | undefined + modifiers?: ts.NodeArray | undefined + _functionLikeDeclarationBrand: any + _declarationBrand: any + _statementBrand: any + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined +} +/* +// TODO: find the difference between this and FunctionDeclaration +export class FunctionExpression extends NodeBase implements ts.FunctionExpression, FunctionLikeDeclarationBase { constructor(peer: KNativePointer) { super(peer) } private get _scriptFunction() { - return nativeModule._FunctionDeclarationFunction(Global.context, this.peer) + return nativeModule._FunctionDeclarationFunction(global.context, this.peer) } get name(): Identifier { - return util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier + return util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier } get body(): Block { - return util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + return util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } get parameters(): NodeArray { - const params = nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction) + const params = nativeModule._ScriptFunctionParams(global.context, this._scriptFunction) return util.unpack(params) as NodeArray } // TODO: support minimal interface + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + type?: TypeNode | undefined _declarationBrand: any - _statementBrand: any - kind: ts.SyntaxKind.FunctionDeclaration = ts.SyntaxKind.FunctionDeclaration + kind: ts.SyntaxKind.FunctionExpression = ts.SyntaxKind.FunctionExpression } +*/ export class Identifier extends Node implements ts.Identifier, Expression { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Identifier) { + super() + this._node = _node + this.text = this._node.name } - get text(): string { - return withStringResult(nativeModule._IdentifierName(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _IdentifierName`) + readonly _node: ets.Identifier + readonly text: string + readonly kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier + + // TODO: support minimal interface + get escapedText(): ts.__String { return todo() } + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any +} + +export class PrivateIdentifier extends Node implements ts.PrivateIdentifier, Expression { + constructor(_node: ets.Identifier) { + super() + this._node = _node + this.text = this._node.name + if (!this._node.isPrivate) { + throwError('identifier expected to be private') + } } + readonly _node: ets.Identifier + readonly text: string + readonly kind: ts.SyntaxKind.PrivateIdentifier = ts.SyntaxKind.PrivateIdentifier + // TODO: support minimal interface get escapedText(): ts.__String { return todo() } _primaryExpressionBrand: any @@ -239,7 +281,6 @@ export class Identifier extends Node implements ts.Identifier, Expression { _unaryExpressionBrand: any _expressionBrand: any _declarationBrand: any - kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier } // TODO: should be interface, not abstract class @@ -249,38 +290,35 @@ export abstract class Statement extends Node implements ts.Statement { } export class Block extends Node implements ts.Block { - constructor(peer: KNativePointer) { - super(peer) - } + constructor(_node: ets.Block) { + super() + this._node = _node - private _statements?: NodeArray - get statements(): NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = util.unpack(statementsPtr) as NodeArray - } - return this._statements + this.statements = unpackNodeArray(this._node.statements) } + readonly _node: ets.Block + + readonly statements: NodeArray + readonly kind: ts.SyntaxKind.Block = ts.SyntaxKind.Block + // 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) - } + constructor(_node: ets.Program) { + super() + this._node = _node - private _statements?: NodeArray - get statements(): NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = util.unpack(statementsPtr) as NodeArray - } - return this._statements + this.statements = unpackNodeArray(this._node.statements) } + readonly _node: ets.Program + + readonly statements: NodeArray + readonly kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile + moduleName: string | undefined getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter { throw new Error("Method not implemented.") } getLineEndOfPosition(pos: number): number { throw new Error("Method not implemented.") } @@ -301,15 +339,25 @@ export class SourceFile extends Node implements ts.SourceFile { get hasNoDefaultLib(): boolean { return todo() } get languageVersion(): ts.ScriptTarget { return todo() } _declarationBrand: any - kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile + impliedNodeFormat?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + modifiers?: ts.NodeArray | undefined } export abstract class Expression extends Node implements ts.Expression { + abstract readonly _node: ets.Node + + // TODO: support minimal interface _expressionBrand: any kind: any } export abstract class LeftHandSideExpression extends Node implements ts.LeftHandSideExpression, Expression { + abstract readonly _node: ets.Node + + // TODO: support minimal interface _leftHandSideExpressionBrand: any _updateExpressionBrand: any _unaryExpressionBrand: any @@ -318,40 +366,32 @@ export abstract class LeftHandSideExpression extends Node implements ts.LeftHand } export class ExpressionStatement extends Node implements ts.ExpressionStatement, Statement { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.ExpressionStatement) { + super() + this._node = _node + this.expression = arktsNodeByEtsNode(this._node.expression) as Expression } - get expression(): Expression { - return util.nodeByPeer(nativeModule._ExpressionStatementGetExpression(Global.context, this.peer)) as Expression - } + readonly _node: ets.ExpressionStatement + readonly kind: ts.SyntaxKind.ExpressionStatement = ts.SyntaxKind.ExpressionStatement + readonly expression: 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.nodeByPeer(nativeModule._CallExpressionCallee(Global.context, this.peer)) as LeftHandSideExpression - } - return this._expression + constructor(_node: ets.CallExpression) { + super() + this._node = _node + this.expression = arktsNodeByEtsNode(this._node.expression) as LeftHandSideExpression + this.arguments = unpackNodeArray(this._node.arguments) } - private _arguments?: NodeArray - get arguments(): NodeArray { - if (this._arguments === undefined) { - const argumentsPtr = nativeModule._CallExpressionArguments(Global.context, this.peer, NULLPTR) - this._arguments = util.unpack(argumentsPtr) as NodeArray - } - return this._arguments - } + readonly _node: ets.CallExpression + readonly kind: ts.SyntaxKind.CallExpression = ts.SyntaxKind.CallExpression + readonly expression: LeftHandSideExpression + readonly arguments: NodeArray // TODO: support minimal interface _leftHandSideExpressionBrand: any @@ -359,29 +399,20 @@ export class CallExpression extends Node implements ts.CallExpression, LeftHandS _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) + constructor(_node: ets.MemberExpression) { + super() + this._node = _node + this.expression = unpackNode(this._node.object) + this.name = unpackNode(this._node.property) } - private _name?: Identifier - get name() { - if (this._name === undefined) { - this._name = util.nodeByPeer(nativeModule._MemberExpressionProperty(Global.context, this.peer)) as Identifier - } - return this._name - } + readonly _node: ets.MemberExpression - private _expression?: LeftHandSideExpression - get expression(): LeftHandSideExpression { - if (this._expression === undefined) { - this._expression = util.nodeByPeer(nativeModule._MemberExpressionObject(Global.context, this.peer)) as LeftHandSideExpression - } - return this._expression - } + readonly expression: LeftHandSideExpression + readonly name: Identifier // TODO: support minimal interface _memberExpressionBrand: any @@ -394,14 +425,16 @@ export class PropertyAccessExpression extends Node implements ts.PropertyAccessE } export class StringLiteral extends Node implements ts.StringLiteral { - constructor(peer: KNativePointer) { - super(peer) - } + constructor(_node: ets.StringLiteral) { + super() + this._node = _node - get text(): string { - return withStringResult(nativeModule._StringLiteralString(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _StringLiteralString`) + this.text = this._node.str } + readonly _node: ets.StringLiteral + readonly text: string + // TODO: support minimal interface _literalExpressionBrand: any _primaryExpressionBrand: any @@ -413,29 +446,37 @@ export class StringLiteral extends Node implements ts.StringLiteral { _declarationBrand: any kind: ts.SyntaxKind.StringLiteral = ts.SyntaxKind.StringLiteral } - -export class ClassDeclaration extends Node implements ts.ClassDeclaration { +/* +export class ClassDeclaration extends NodeBase 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 NodeArray - this.name = util.nodeByPeer(nativeModule._ClassDefinitionIdent(Global.context, this._definition)) as Identifier + + this._definition = nativeModule._ClassDeclarationDefinition(global.context, peer) + this.members = util.unpack(nativeModule._ClassDefinitionBody(global.context, this._definition)) as NodeArray + this.name = util.nodeByPeer(nativeModule._ClassDefinitionIdent(global.context, this._definition)) as Identifier + + const _typeParamDecl = nativeModule._ClassDefinitionTypeParamsConst(global.context, this._definition) + this._typeParameters = (_typeParamDecl !== NULLPTR) ? nativeModule._TSTypeParameterDeclarationParamsConst(global.context, _typeParamDecl, NULLPTR) : NULLPTR + this.typeParameters = (this._typeParameters !== NULLPTR) ? (util.unpack(this._typeParameters) as NodeArray) : undefined } private _definition readonly members: NodeArray + readonly name: Identifier + private readonly _typeParameters: KNativePointer + readonly typeParameters?: NodeArray | undefined; + // TODO: support minimal interface _declarationBrand: any _statementBrand: any kind: ts.SyntaxKind.ClassDeclaration = ts.SyntaxKind.ClassDeclaration } - +*/ export abstract class ClassElement extends Node implements ts.ClassElement { - // tsc: readonly name?: PropertyName - readonly name?: Identifier + readonly name?: PropertyName // TODO: support minimal interface _declarationBrand: any @@ -443,14 +484,88 @@ export abstract class ClassElement extends Node implements ts.ClassElement { kind: any } +export type MemberName = Identifier | PrivateIdentifier; + +// TODO: support +// export type PropertyName = Identifier | StringLiteral | NumericLiteral | ts.ComputedPropertyName | PrivateIdentifier; +export type PropertyName = Identifier | StringLiteral | NumericLiteral | PrivateIdentifier; + +// TODO: support +export type DeclarationName = + | PropertyName + // | JsxAttributeName + // | StringLiteralLike + // | ElementAccessExpression + // | BindingPattern + // | EntityNameExpression; + +export interface Declaration extends Node { + _declarationBrand: any +} + + +export abstract class NamedDeclaration extends Node implements ts.NamedDeclaration, Declaration { + name?: DeclarationName + _declarationBrand: any +} +/* +export type SignatureDeclaration = ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration | MethodSignature | ts.IndexSignatureDeclaration | FunctionTypeNode | ts.ConstructorTypeNode | ts.JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | ts.AccessorDeclaration | FunctionExpression | ArrowFunction; + +export interface SignatureDeclarationBase extends NamedDeclaration { + readonly kind: SignatureDeclaration["kind"]; + readonly name?: PropertyName; + readonly typeParameters?: NodeArray | undefined; + readonly parameters: NodeArray; + readonly type?: TypeNode | undefined; +} + +export type VariableLikeDeclaration = ts.VariableDeclaration | ParameterDeclaration | ts.BindingElement | PropertyDeclaration | ts.PropertyAssignment | PropertySignature | ts.JsxAttribute | ts.ShorthandPropertyAssignment | ts.EnumMember | ts.JSDocPropertyTag | ts.JSDocParameterTag; + +export interface FunctionLikeDeclarationBase extends SignatureDeclarationBase { + _functionLikeDeclarationBrand: any; + readonly asteriskToken?: ts.AsteriskToken | undefined; + readonly questionToken?: ts.QuestionToken | undefined; + readonly exclamationToken?: ts.ExclamationToken | undefined; + readonly body?: Block | Expression | undefined; +} + +// TODO: support +// export type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; +export type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + +export class MethodSignature extends NodeBase implements ts.MethodSignature, SignatureDeclarationBase { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + get parent(): any { return todo() } + // name: PropertyName + name: any + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _typeElementBrand: any + questionToken?: ts.QuestionToken | undefined + kind: ts.SyntaxKind.MethodSignature = ts.SyntaxKind.MethodSignature +} + // ets: MethodDefinition -export class MethodDeclaration extends Node implements ts.MethodDeclaration, ClassElement { +export class MethodDeclaration extends NodeBase implements ts.MethodDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._MethodDefinitionFunction(Global.context, peer) - this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + + this._scriptFunction = nativeModule._MethodDefinitionFunction(global.context, peer) + this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(global.context, this._scriptFunction)) as NodeArray + if (util.scriptFunctionHasBody(this._scriptFunction)) { + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block + } } // tsc: readonly name?: PropertyName @@ -459,7 +574,7 @@ export class MethodDeclaration extends Node implements ts.MethodDeclaration, Cla readonly parameters: NodeArray // tsc: readonly body?: FunctionBody | undefined - readonly body: Block + readonly body?: Block | undefined private readonly _scriptFunction: KNativePointer @@ -473,13 +588,14 @@ export class MethodDeclaration extends Node implements ts.MethodDeclaration, Cla } // ets: MethodDefinition -export class ConstructorDeclaration extends Node implements ts.ConstructorDeclaration, ClassElement { +export class ConstructorDeclaration extends NodeBase implements ts.ConstructorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._MethodDefinitionFunction(Global.context, peer) - this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + + this._scriptFunction = nativeModule._MethodDefinitionFunction(global.context, peer) + this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(global.context, this._scriptFunction)) as NodeArray + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } // tsc: readonly name?: PropertyName @@ -501,101 +617,262 @@ export class ConstructorDeclaration extends Node implements ts.ConstructorDeclar kind: ts.SyntaxKind.Constructor = ts.SyntaxKind.Constructor } -export class PropertyDeclaration extends Node implements ts.PropertyDeclaration { +export class PropertySignature extends NodeBase implements ts.TypeElement { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + _typeElementBrand: any + name?: PropertyName | undefined + questionToken?: ts.QuestionToken | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.PropertySignature = ts.SyntaxKind.PropertySignature +} + +export class PropertyDeclaration extends NodeBase implements ts.PropertyDeclaration, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface get parent(): any { return todo() } - get name(): ts.PropertyName { return todo() } + get name(): PropertyName { return todo() } _classElementBrand: any _declarationBrand: any kind: ts.SyntaxKind.PropertyDeclaration = ts.SyntaxKind.PropertyDeclaration } -export class ParameterDeclaration extends Node implements ts.ParameterDeclaration { +export class GetAccessorDeclaration extends NodeBase implements ts.GetAccessorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface get parent(): any { return todo() } - get name(): ts.BindingName { return todo() } + // name: PropertyName + name: any + body?: Block | undefined + _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined _declarationBrand: any - kind: ts.SyntaxKind.Parameter = ts.SyntaxKind.Parameter + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _classElementBrand: any + _typeElementBrand: any + _objectLiteralBrand: any + kind: ts.SyntaxKind.GetAccessor = ts.SyntaxKind.GetAccessor } -export class ETSPrimitiveType extends Node implements ts.Node, TypeNode { +export class SetAccessorDeclaration extends NodeBase implements ts.SetAccessorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface - _typeNodeBrand: any - kind: ts.SyntaxKind.Unknown = ts.SyntaxKind.Unknown + get parent(): any { return todo() } + // name: PropertyName + name: any + body?: Block | undefined + _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _classElementBrand: any + _typeElementBrand: any + _objectLiteralBrand: any + kind: ts.SyntaxKind.SetAccessor = ts.SyntaxKind.SetAccessor +} +*/ +export class ParameterDeclaration extends Node implements ts.ParameterDeclaration, NamedDeclaration { + constructor(_node: ets.ETSParameterExpression) { + super() + this._node = _node + } + + readonly _node: ets.ETSParameterExpression + + readonly kind: ts.SyntaxKind.Parameter = ts.SyntaxKind.Parameter + + // TODO: support minimal interface + get name(): Identifier { return todo() } + _declarationBrand: any +} +/* +export type BindingName = Identifier | ts.BindingPattern; + +// ets: VariableDeclaratorId +export class VariableDeclaration extends NodeBase implements ts.VariableDeclaration, NamedDeclaration { + constructor(peer: KNativePointer) { + super(peer) + + this.name = util.nodeByPeer(nativeModule._VariableDeclaratorId(global.context, this.peer)) as Identifier + } + + name: Identifier + + // TODO: support minimal interface + get parent(): any { return todo() } + exclamationToken?: ts.ExclamationToken | undefined + type?: ts.TypeNode | undefined + initializer?: ts.Expression | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.VariableDeclaration = ts.SyntaxKind.VariableDeclaration +} + +export class VariableDeclarationList extends NodeBase implements ts.VariableDeclarationList { + constructor(peer: KNativePointer) { + super(peer) + + this.declarations = util.unpack(nativeModule._VariableDeclarationDeclaratorsConst(global.context, this.peer)) as NodeArray + } + + // TODO: support minimal interface + get parent(): any { return todo() } + readonly declarations: NodeArray + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.VariableDeclarationList = ts.SyntaxKind.VariableDeclarationList +} +*/ +export class TypeParameterDeclaration extends Node implements ts.TypeParameterDeclaration { + constructor(_node: ets.TSTypeParameter) { + super() + this._node = _node + this.name = unpackNode(this._node.name) + } + + readonly _node: ets.TSTypeParameter + + readonly name: Identifier + + readonly kind: ts.SyntaxKind.TypeParameter = ts.SyntaxKind.TypeParameter + + // TODO: support minimal interface + constraint?: ts.TypeNode | undefined + default?: ts.TypeNode | undefined + expression?: ts.Expression | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined } // TODO: should be interface, not abstract class export abstract class TypeNode extends Node implements ts.TypeNode { + // TODO: support minimal interface _typeNodeBrand: any kind: any } export class KeywordTypeNode extends Node implements ts.KeywordTypeNode, TypeNode { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.ETSPrimitiveType | ets.ETSTypeReference) { + super() + this._node = _node } + readonly _node: ets.ETSPrimitiveType | ets.ETSTypeReference + + readonly kind: ts.KeywordTypeSyntaxKind = ts.SyntaxKind.UnknownKeyword + // 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) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + + readonly kind: ts.SyntaxKind.TypeReference = ts.SyntaxKind.TypeReference + // TODO: support minimal interface _typeNodeBrand: any typeName: any - kind: ts.SyntaxKind.TypeReference = ts.SyntaxKind.TypeReference } +// export class FunctionTypeNode extends Node implements ts.FunctionTypeNode, TypeNode, SignatureDeclarationBase { export class FunctionTypeNode extends Node implements ts.FunctionTypeNode, TypeNode { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + + readonly kind: ts.SyntaxKind.FunctionType = ts.SyntaxKind.FunctionType + // TODO: support minimal interface - get parent(): any { return todo() } - get parameters(): ts.NodeArray { return todo() } + readonly name?: PropertyName; + get parameters(): 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) +export class UnionTypeNode extends Node implements ts.UnionTypeNode, TypeNode { + constructor(_node: ets.UnionTypeNode) { + super() + this._node = _node + this.types = unpackNodeArray(this._node.types) } - private _expression?: Expression - get expression(): Expression | undefined { - if (this._expression === undefined) { - this._expression = util.nodeByPeer(nativeModule._ReturnStatementArgument(Global.context, this.peer)) as Expression - } - return this._expression + readonly _node: ets.UnionTypeNode + + readonly types: NodeArray + + readonly kind: ts.SyntaxKind.UnionType = ts.SyntaxKind.UnionType + + // TODO: support minimal interface + _typeNodeBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined +} + +export class ReturnStatement extends Node implements ts.ReturnStatement, Statement { + constructor(_node: ets.ReturnStatement) { + super() + this._node = _node + this.expression = unpackNullableNode(this._node.argument) } + readonly _node: ets.ReturnStatement + + readonly expression: Expression | undefined + + readonly kind: ts.SyntaxKind.ReturnStatement = ts.SyntaxKind.ReturnStatement + // TODO: support minimal interface _statementBrand: any - kind: ts.SyntaxKind.ReturnStatement = ts.SyntaxKind.ReturnStatement } - -export class IfStatement extends Node implements ts.IfStatement { +/* +export class IfStatement extends NodeBase implements ts.IfStatement { constructor(peer: KNativePointer) { super(peer) } @@ -607,7 +884,7 @@ export class IfStatement extends Node implements ts.IfStatement { kind: ts.SyntaxKind.IfStatement = ts.SyntaxKind.IfStatement } -export class BinaryExpression extends Node implements ts.BinaryExpression { +export class BinaryExpression extends NodeBase implements ts.BinaryExpression { constructor(peer: KNativePointer) { super(peer) } @@ -621,12 +898,27 @@ export class BinaryExpression extends Node implements ts.BinaryExpression { kind: ts.SyntaxKind.BinaryExpression = ts.SyntaxKind.BinaryExpression } -export class ArrowFunction extends Node implements ts.ArrowFunction { +export class AssignmentExpression extends NodeBase implements ts.AssignmentExpression { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._ArrowFunctionExpressionFunction(Global.context, this.peer) - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + } + + // TODO: support minimal interface + right: any + _expressionBrand: any + _declarationBrand: any + readonly left: any + readonly operatorToken: any + kind: ts.SyntaxKind.BinaryExpression = ts.SyntaxKind.BinaryExpression +} + +export class ArrowFunction extends NodeBase 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 NodeArray + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } get name(): never { @@ -645,16 +937,21 @@ export class ArrowFunction extends Node implements ts.ArrowFunction { _declarationBrand: any readonly kind: ts.SyntaxKind.ArrowFunction = ts.SyntaxKind.ArrowFunction } +*/ +export class NumericLiteral extends Node implements ts.NumericLiteral, Declaration { + constructor(_node: ets.NumberLiteral) { + super() + this._node = _node -export class NumericLiteral extends Node implements ts.NumericLiteral { - constructor(peer: KNativePointer) { - super(peer) + this.text = this._node.str } + readonly _node: ets.NumberLiteral + readonly text: string + // TODO: support minimal interface _literalExpressionBrand: any _declarationBrand: any - text: any _primaryExpressionBrand: any _memberExpressionBrand: any _leftHandSideExpressionBrand: any @@ -663,26 +960,32 @@ export class NumericLiteral extends Node implements ts.NumericLiteral { _expressionBrand: any readonly kind: ts.SyntaxKind.NumericLiteral = ts.SyntaxKind.NumericLiteral } - -export class VariableStatement extends Node implements ts.VariableStatement { +/* +// ets: VariableDeclaration +export class VariableStatement extends NodeBase implements ts.VariableStatement { constructor(peer: KNativePointer) { super(peer) + + this.declarationList = factory.createVariableDeclarationList(util.unpack(nativeModule._VariableDeclarationDeclaratorsConst(global.context, this.peer)) as NodeArray) } // TODO: support minimal interface - modifiers?: ts.NodeArray | undefined - declarationList: any + readonly declarationList: VariableDeclarationList; _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) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + kind: ts.SyntaxKind = UNSUPPORTED_KIND } diff --git a/arkoala-arkts/libarkts/src/arkts/typesEts.ts b/arkoala-arkts/libarkts/src/arkts/typesEts.ts new file mode 100644 index 0000000000000000000000000000000000000000..73dbd63f1e3821952a22591671af8cf06d5abf78 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/typesEts.ts @@ -0,0 +1,609 @@ +import { nativeModule } from "../NativeModule" +import { KInt, KNativePointer as KPtr, withStringResult, withStringArray, KNativePointer } from "@koalaui/interop" +import * as util from "./utilities" +import global from "./global" +import * as arkts from "." +import { + Es2pandaPrimitiveType, + Es2pandaModifierFlags, + SyntaxKind, + Es2pandaScriptFunctionFlags, + es2pandaKind, +} from "./enums" +import { + throwError, + passString, + passEtsNode, + passEtsNodeArray, + unpackEtsNode, + unpackEtsNodeArray, + etsNodeByPeer, + etsNodeByPeerNullable, +} from "./utilities" +import { updateChildren } from "./factory/utilities" + +export const NULLPTR: KPtr = BigInt(0) + +export const NULLPTR_ARRAY = new BigUint64Array([NULLPTR]) + +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 + ) + +function assertValidPeer(peer: KPtr, expectedKind: es2pandaKind): void { + if (peer === NULLPTR) { + throwError(`invalid peer: NULLPTR`) + } + const peerKind = nativeModule._GetKind(global.context, peer) + if (peerKind !== expectedKind) { + throwError(`invalid kind of peer: ${peerKind} expected: ${expectedKind}`) + } +} + +export abstract class EtsObject { + constructor(peer: KPtr) { + this.peer = peer + } + + // pointer associated with native object + readonly peer: KPtr +} + +export abstract class Node extends EtsObject { + constructor(peer: KPtr) { + if (peer === NULLPTR) { + throw new Error('trying to create new Node on NULLPTR') + } + super(peer) + this.kind = nativeModule._GetKind(global.context, this.peer) + nativeModule._AstNodeUpdateChildren(global.context, peer) + } + + readonly kind: es2pandaKind + + dumpJson(): string { + return withStringResult(nativeModule._AstNodeDumpJsonConst(global.context, this.peer)) ?? throwError('failed to dump Json') + } + + dumpSrc(): string { + return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(global.context, this.peer)) ?? throwError('failed to dump Src') + } + + dumpModifierFlags(): string { + return withStringResult(nativeModule._AstNodeDumpModifiers(global.context, this.peer)) ?? throwError('failed to dump ModifierFlags') + } + + get parent(): KPtr { + const _parent = nativeModule._AstNodeParent(global.context, this.peer) + if (_parent === NULLPTR) { + util.throwError('BAD ACCESS: PARENT IS NULLPTR') + } + return _parent + } + + set parent(peer: KPtr) { + nativeModule._AstNodeSetParent(global.context, this.peer, peer) + } + + get modifierFlags(): KInt { + return nativeModule._AstNodeModifiers(global.context, this.peer) + } + + set modifierFlags(flags: KInt | undefined) { + nativeModule._AstNodeClearModifier(global.context, this.peer, ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, this.peer, flags ?? Es2pandaModifierFlags.MODIFIER_FLAGS_NONE) + } +} + +// export abstract class Node extends EtsNode { +// constructor(peer: KPtr) { +// super(peer) +// this.kind = nativeModule._GetKind(global.context, this.peer) +// updateChildren(this.peer) +// } + +// readonly kind: es2pandaKind +// } + +// export abstract class CompatibleNode extends EtsNode { +// constructor(peer: KPtr, related: arkts.Node) { +// super(peer) +// this.kind = nativeModule._GetKind(global.context, this.peer) +// updateChildren(this.peer) +// this.related = related +// } + +// readonly kind: es2pandaKind +// readonly related: arkts.Node +// } + +export abstract class UnsupportedNode extends Node { + constructor(peer: KPtr) { + super(peer) + throw new Error('trying to create UnsupportedNode') + } +} + +export class Config extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } +} + +export class Context extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } +} + +export class Program extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Program) + super(peer) + } + + static create( + source: string + ): Program { + if (!global.isInitializedConfig()) { + global.config = withStringArray(["", "--arktsconfig", "./arktsconfig.json", "./input/main.sts"], (stringArray: string[]) => { + return nativeModule._CreateConfig(4, stringArray) + }) + } + global.context = nativeModule._CreateContextFromString(global.config, passString(source), passString("./input/main.sts")) + + // TODO: rewrite this maybe + arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) + + return new Program(nativeModule._ProgramAst(nativeModule._ContextProgram(global.context))) + } + + get statements(): readonly Node[] { + return unpackEtsNodeArray(nativeModule._BlockStatementStatements(global.context, this.peer)) + } + + set statements(nodes: readonly Node[]) { + nativeModule._BlockStatementSetStatements(global.context, this.peer, passEtsNodeArray(nodes), nodes.length) + } +} + +export class ExpressionStatement extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ExpressionStatement) + super(peer) + this.expression = etsNodeByPeer(nativeModule._ExpressionStatementGetExpression(global.context, this.peer)) + } + + static create(expression: Node): ExpressionStatement { + return new ExpressionStatement(nativeModule._CreateExpressionStatement(global.context, expression.peer)) + } + + readonly expression: Node +} + +export class CallExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.CallExpression) + super(peer) + this.expression = unpackEtsNode(nativeModule._CallExpressionCallee(global.context, this.peer)) + this.arguments = unpackEtsNodeArray(nativeModule._CallExpressionArguments(global.context, this.peer, NULLPTR)) + } + + static create( + expression: Node, + typeParamsDecl: TSTypeParameterDeclaration | undefined, + args: Node[] | undefined + ): CallExpression { + return new CallExpression( + nativeModule._CreateCallExpression( + global.context, + passEtsNode(expression), + passEtsNodeArray(args), + args?.length ?? 0, + passEtsNode(typeParamsDecl), + false, + false + ) + ) + } + + readonly expression: Node + readonly arguments: readonly Node[] +} + +export class MemberExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.MemberExpression) + super(peer) + this.object = unpackEtsNode(nativeModule._MemberExpressionObject(global.context, this.peer)) + this.property = unpackEtsNode(nativeModule._MemberExpressionProperty(global.context, this.peer)) + } + + static create( + object: Node, + property: Node, + kind: KInt, + computed: boolean, + optional: boolean + ): MemberExpression { + return new MemberExpression( + nativeModule._CreateMemberExpression( + global.context, + passEtsNode(object), + passEtsNode(property), + kind, + computed, + optional + ) + ) + } + + readonly object: Node + readonly property: Node +} + +export class ETSPrimitiveType extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSPrimitiveType) + super(peer) + } + + static create( + type: Es2pandaPrimitiveType + ): ETSPrimitiveType { + return new ETSPrimitiveType( + nativeModule._CreateETSPrimitiveType(global.context, type) + ) + } + + // readonly type: Es2pandaPrimitiveType +} + +export class ETSTypeReference extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSTypeReference) + super(peer) + } + + static create( + typeName: Identifier + ): ETSTypeReference { + return new ETSTypeReference( + nativeModule._CreateETSTypeReference( + global.context, + ETSTypeReferencePart.create(typeName).peer + ) + ) + } + + // readonly typeName: Identifier + // readonly typeRefPart: TypeReferencePart +} + +export class ETSTypeReferencePart extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSTypeReferencePart) + super(peer) + } + + // TODO: support type params and prev + static create(typeName: Identifier) { + typeName.setReference(true) + // TODO: support type params and prev + return new ETSTypeReferencePart( + nativeModule._CreateETSTypeReferencePart( + global.context, + typeName.peer, + NULLPTR, + NULLPTR + ) + ) + } + + // readonly typeName: Identifier +} + +export class UnionTypeNode extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSUnionType) + super(peer) + this.types = unpackEtsNodeArray(nativeModule._ETSUnionTypeIrTypesConst(global.context, this.peer, NULLPTR)) + } + + readonly types: readonly Node[] +} + +export class FunctionTypeNode extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSFunctionType) + super(peer) + } +} + +export class Identifier extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Identifier) + super(peer) + this.isPrivate = nativeModule._IdentifierIsPrivateIdentConst(global.context, this.peer) + } + + static create(name: string, typeAnnotation?: Node): Identifier { + if (typeAnnotation === undefined) { + return new Identifier(nativeModule._CreateIdentifier1(global.context, passString(name))) + } else { + return new Identifier(nativeModule._CreateIdentifier2(global.context, passString(name), typeAnnotation.peer)) + } + } + + // TODO: return (string | undefined) maybe + get name(): string { + return withStringResult(nativeModule._IdentifierName(global.context, this.peer)) ?? util.throwError('name is undefined') + } + + set name(name: string) { + nativeModule._IdentifierSetName(global.context, this.peer, passString(name)) + } + + readonly isPrivate: boolean + + setReference(isRef: boolean): void { + nativeModule._IdentifierSetReference(global.context, this.peer, isRef) + } + + // TODO: + // typeAnnotation() + // isOptional() + // setOptional() + // setTsVariables() +} + +export class StringLiteral extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.StringLiteral) + super(peer) + this.str = withStringResult(nativeModule._StringLiteralStrConst(global.context, this.peer)) ?? util.throwError('str is undefined') + } + + static create(str: string): StringLiteral { + return new StringLiteral(nativeModule._CreateStringLiteral(global.context, passString(str))) + } + + readonly str: string +} + +export class NumberLiteral extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.NumberLiteral) + super(peer) + this.str = withStringResult(nativeModule._NumberLiteralStrConst(global.context, this.peer)) ?? util.throwError('str is undefined') + } + + static create(str: string): NumberLiteral { + return new NumberLiteral(nativeModule._CreateNumberLiteral(global.context, passString(str))) + } + + readonly str: string +} + +export class FunctionSignature extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } + + static create( + typeParamsDecl: TSTypeParameterDeclaration | undefined, + params: Node[], + returnTypeAnnotation: Node | undefined, + ): FunctionSignature { + return new FunctionSignature( + nativeModule._CreateFunctionSignature( + global.context, + passEtsNode(typeParamsDecl), + passEtsNodeArray(params), + params.length, + passEtsNode(returnTypeAnnotation) + ) + ) + } +} + +export class ScriptFunction extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ScriptFunction) + super(peer) + } + + static create( + body: Node | undefined, + signature: FunctionSignature, + functionFlags: Es2pandaScriptFunctionFlags, + modifierFlags: Es2pandaModifierFlags, + declare: boolean, + ident: Identifier | undefined + ): ScriptFunction { + const peer = nativeModule._CreateScriptFunction( + global.context, + passEtsNode(body), + signature.peer, + functionFlags, + modifierFlags, + declare + ) + if (ident !== undefined) { + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident.peer) + updateChildren(peer) + } + return new ScriptFunction(peer) + } +} + +export class FunctionDeclaration extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.FunctionDeclaration) + super(peer) + this.scriptFunction = etsNodeByPeer(nativeModule._FunctionDeclarationFunction(global.context, this.peer)) + this.parameters = unpackEtsNodeArray(nativeModule._ScriptFunctionParams(global.context, this.scriptFunction.peer)) + this.name = etsNodeByPeerNullable(nativeModule._ScriptFunctionId(global.context, this.scriptFunction.peer)) + this.body = etsNodeByPeerNullable(nativeModule._ScriptFunctionBody(global.context, this.scriptFunction.peer)) + this.typeParamsDecl = etsNodeByPeerNullable(nativeModule._ScriptFunctionTypeParams(global.context, this.scriptFunction.peer)) + this.type = etsNodeByPeerNullable(nativeModule._ScriptFunctionReturnTypeAnnotation(global.context, this.scriptFunction.peer)) + this.isAnon = nativeModule._FunctionDeclarationIsAnonymousConst(global.context, this.peer) + } + + static create( + scriptFunction: ScriptFunction, + isAnon: boolean + ): FunctionDeclaration { + const node = new FunctionDeclaration( + nativeModule._CreateFunctionDeclaration( + global.context, + scriptFunction.peer, + isAnon + ) + ) + // TODO: maybe wrong + node.modifierFlags = scriptFunction.modifierFlags + return node + } + + readonly scriptFunction: ScriptFunction + readonly parameters: readonly Node[] + readonly name?: Identifier + readonly body?: Block + readonly typeParamsDecl?: TSTypeParameterDeclaration + readonly type?: Node + readonly isAnon: boolean +} + +// export class FunctionExpression extends Node { +// constructor( +// expression: Node +// ) { +// super(nativeModule._CreateFunctionExpression( +// global.context, +// expression.peer +// )) +// this.expression = expression +// } + +// readonly expression: Node +// } + +export class Block extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Block) + super(peer) + this.statements = unpackEtsNodeArray(nativeModule._BlockStatementStatements(global.context, this.peer)) + } + + static create( + statements: Node[] + ): Block { + return new Block( + nativeModule._CreateBlockStatement( + global.context, + passEtsNodeArray(statements), + statements.length + ) + ) + } + + readonly statements: readonly Node[] +} + +export class ETSParameterExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSParameterExpression) + super(peer) + } + + static create( + identifier: Identifier, + initializer: Node | undefined + ): ETSParameterExpression { + return new ETSParameterExpression( + nativeModule._CreateETSParameterExpression( + global.context, + passEtsNode(identifier), + passEtsNode(initializer) + ) + ) + } +} + +export class TSTypeParameterDeclaration extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSTypeParameterDeclaration) + super(peer) + this.parameters = unpackEtsNodeArray(nativeModule._TSTypeParameterDeclarationParamsConst(global.context, this.peer, NULLPTR)) + } + + static create( + parameters: TSTypeParameter[], + ): TSTypeParameterDeclaration { + return new TSTypeParameterDeclaration( + nativeModule._CreateTSTypeParameterDeclaration( + global.context, + passEtsNodeArray(parameters), + parameters.length, + // TODO: fix + parameters.length + ) + ) + } + + readonly parameters: readonly TSTypeParameter[] +} + +export class TSTypeParameter extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSTypeParameter) + super(peer) + this.name = etsNodeByPeer(nativeModule._TSTypeParameterName(global.context, this.peer)) + } + + static create( + name: Identifier, + constraint: Node | undefined, + defaultType: Node | undefined, + modifierFlags: KInt, + ): TSTypeParameter { + const peer = nativeModule._CreateTSTypeParameter( + global.context, + passEtsNode(name), + passEtsNode(constraint), + passEtsNode(defaultType) + ) + nativeModule._AstNodeClearModifier(global.context, peer, ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, peer, modifierFlags) + return new TSTypeParameter(peer) + } + + readonly name: Identifier +} + +export class ReturnStatement extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ReturnStatement) + super(peer) + this.argument = etsNodeByPeerNullable( + nativeModule._ReturnStatementArgument(global.context, this.peer) + ) + } + + static create( + argument: Node + ): ReturnStatement { + return new ReturnStatement( + nativeModule._CreateReturnStatement1( + global.context, + passEtsNode(argument) + ) + ) + } + + readonly argument: Node | undefined +} diff --git a/arkoala-arkts/libarkts/src/arkts/utilities.ts b/arkoala-arkts/libarkts/src/arkts/utilities.ts index ef8db6e8c25b679e2c5ef39f5d82a93afa4c99d2..2d9e1fdd69801c4be1a7446a44c0425893b1de58 100644 --- a/arkoala-arkts/libarkts/src/arkts/utilities.ts +++ b/arkoala-arkts/libarkts/src/arkts/utilities.ts @@ -13,13 +13,25 @@ * limitations under the License. */ -import { nativeModule } from "../NativeModule" -import { fromPtrArray, KNativePointer, withStringResult, withString } from "@koalaui/interop" +import { KNativePointerArray, nativeModule } from "../NativeModule" +import { fromPtrArray, KNativePointer, withStringResult, withString, KInt } from "@koalaui/interop" import { NativePtrDecoder } from "../node/Platform" -import * as arkts from "./types" +import global from "./global" +import * as arkts from "." +import { + Es2pandaModifierFlags, + Es2pandaScriptFunctionFlags, +} from "./enums" +import * as ets from "./typesEts" -import { nodeByPeer } from "./nodeByPeer" -export { nodeByPeer } from "./nodeByPeer" +import { arktsNodeByEtsNode } from "./arktsNodeByEtsNode" +export { arktsNodeByEtsNode } from "./arktsNodeByEtsNode" + +import { etsNodeByPeer } from "./etsNodeByPeer" +export { etsNodeByPeer } from "./etsNodeByPeer" + +import { etsNodeByPeerNullable } from "./etsNodeByPeer" +export { etsNodeByPeerNullable } from "./etsNodeByPeer" export function throwError(error: string): never { throw new Error(error) @@ -29,45 +41,156 @@ export function todo(): any { throwError("Not yet implemented") } -/** TODO batch this */ -export function unpack(arrayPtr: KNativePointer): ReadonlyArray { - const array = (new NativePtrDecoder).decode(arrayPtr) +// /** TODO batch this */ +// export function unpack(arrayPtr: KNativePointer): ReadonlyArray { +// if (arrayPtr === arkts.NULLPTR) { +// return [] +// } +// const array = (new NativePtrDecoder).decode(arrayPtr) - return fromPtrArray(array, (peer: KNativePointer) => { - return nodeByPeer(peer) +// return fromPtrArray(array, (peer: KNativePointer) => { +// return nodeByPeer(peer) +// }) +// } + +export function contextProgram(): KNativePointer { + return nativeModule._ContextProgram(global.context) +} + +// export function programAst(program: KNativePointer) { +// return nodeByPeer(nativeModule._ProgramAst(program)) +// } + +export function dumpJson(peer: KNativePointer): string { + return withStringResult(nativeModule._AstNodeDumpJsonConst(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(global.context, node.peer)) ?? throwError(`COULDN'T DUMP TO SOURCE`) +// } + +// export function dumpModifiers(peer: KNativePointer): string { +// return withStringResult(nativeModule._AstNodeDumpModifiers(global.context, peer)) ?? throwError(`COULDN'T DUMP MODIFIERS`) +// } + +// export function dumpModifiersNode(node: arkts.Node): string { +// return dumpModifiers(node.peer) +// } + +export function createAstDumper(peer: KNativePointer, source: string): KNativePointer { + return withString(source, (_source: string) => { + return nativeModule._CreateAstDumper(global.context, peer, _source) }) } -export function contextProgram(): KNativePointer { - return nativeModule._ContextProgram(arkts.Global.context) +export function scriptFunctionHasBody(peer: KNativePointer): boolean { + const flags = nativeModule._ScriptFunctionFlagsConst(global.context, peer) + return true + && ((flags & Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_EXTERNAL) === 0) + && ((flags & Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_EXTERNAL_OVERLOAD) === 0) } -export function programAst(program: KNativePointer) { - return nodeByPeer(nativeModule._ProgramAst(program)) +function* bits(flags: KInt) { + let bit: KInt = 1 + while (flags >= bit) { + if ((flags & bit) > 0) { + yield bit + } + bit <<= 1 + } } -export function dumpJson(peer: KNativePointer): string { - return withStringResult(nativeModule._AstNodeDumpJsonConst(arkts.Global.context, peer)) ?? throwError(`COULDN'T DUMP TO JSON`) +export function packModifiers(modifiers: ReadonlyArray): KInt { + return modifiers.map( + (mod: arkts.Modifier | undefined | Es2pandaModifierFlags): Es2pandaModifierFlags => { + if (mod === undefined) { + return Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + } + if (typeof mod === 'object') { + return (global.modifierFlags.get(mod.kind) ?? throwError(`Unsupported modifier: ${mod.kind}`)) + } + return mod + }).reduce( + (prev, curr) => (prev | curr), + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + ) } -export function dumpJsonNode(node: arkts.Node): string { - return dumpJson(node.peer) +export function unpackModifiers(modifiers: KInt): ReadonlyArray { + let mods: arkts.Modifier[] = [] + for (const bit of bits(modifiers)) { + mods.push(new arkts.Modifier(global.translateModifiers.get(bit) ?? throwError(`Unsupported modifier: ${bit}`))) + } + return mods } -export function dumpSrcNode(node: arkts.Node): string { - return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(arkts.Global.context, node.peer)) ?? throwError(`COULDN'T DUMP TO SOURCE`) +export function passString(str: string): string { + return withString(str, (_str: string) => _str) } -export function dumpModifiers(peer: KNativePointer): string { - return withStringResult(nativeModule._AstNodeDumpModifiers(arkts.Global.context, peer)) ?? throwError(`COULDN'T DUMP MODIFIERS`) +export function passEtsNode(node: ets.Node | undefined): KNativePointer { + return node?.peer ?? ets.NULLPTR } -export function dumpModifiersNode(node: arkts.Node): string { - return dumpModifiers(node.peer) +export function passEtsNodeArray(nodes: readonly ets.Node[] | undefined): BigUint64Array { + return new BigUint64Array((nodes === undefined) ? [] : nodes.map(node => BigInt(node.peer))) } -export function createAstDumper(peer: KNativePointer, source: string): KNativePointer { - return withString(source, (_source: string) => { - return nativeModule._CreateAstDumper(arkts.Global.context, peer, _source) +export function passNodeArray(nodes: readonly arkts.Node[]): T[] +export function passNodeArray(nodes: readonly arkts.Node[] | undefined): T[] | undefined +export function passNodeArray(nodes: readonly arkts.Node[] | undefined): T[] | undefined { + if (nodes === undefined) { + return undefined + } + return nodes.map((node: arkts.Node) => ((node._node as T) ?? throwError('trying to pass non-compatible node'))) +} + +export function unpackEtsNode(peer: KNativePointer): ets.Node { + if (peer === ets.NULLPTR) { + throwError('nodePtr is NULLPTR') + } + return etsNodeByPeer(peer) +} + +export function unpackEtsNodeArray(nodesPtr: KNativePointer): readonly T[] { + if (nodesPtr === ets.NULLPTR) { + return [] + } + const array = (new NativePtrDecoder).decode(nodesPtr) + + return fromPtrArray(array, (peer: KNativePointer) => { + return etsNodeByPeer(peer) }) } + +export function unpackNode(node: ets.Node): T +export function unpackNode(node: ets.Node | undefined): T | undefined +export function unpackNode(node: ets.Node | undefined): T | undefined { + if (node === undefined) { + return undefined + } + // TODO: add asserts + return arktsNodeByEtsNode(node) as T +} + +export function unpackNullableNode(node: ets.Node | undefined): T | undefined { + if (node === undefined) { + return undefined + } + // TODO: add asserts + return arktsNodeByEtsNode(node) as T +} + +export function unpackNodeArray(nodes: readonly ets.Node[]): arkts.NodeArray +export function unpackNodeArray(nodes: readonly ets.Node[] | undefined): arkts.NodeArray | undefined +export function unpackNodeArray(nodes: readonly ets.Node[] | undefined): arkts.NodeArray | undefined { + if (nodes === undefined) { + return undefined + } + // TODO: add asserts + return nodes.map((node: ets.Node) => arktsNodeByEtsNode(node)) as ReadonlyArray as arkts.NodeArray +} diff --git a/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts b/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts index 8ac100d1abb4e5795ba0890ab5cd121c2f757025..42d4dc1f494ee0cef477eb2faf7ec6e53329ca7b 100644 --- a/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts +++ b/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts @@ -15,11 +15,12 @@ import { nativeModule } from "../NativeModule" import { KNativePointer, withString, withStringArray, withStringResult } from "@koalaui/interop" -import * as arkts from "./types" +import * as arkts from "." +import global from "./global" import { ContextState, } from "./enums" -import { nodeByPeer } from "./nodeByPeer" +// import { nodeByPeer } from "./nodeByPeer" import { throwError } from "./utilities" export function createConfig(input: string[]): KNativePointer { @@ -37,9 +38,14 @@ export function createContextFromString(config: KNativePointer, source: string, } export function proceedToState(state: ContextState): void { - nativeModule._ProceedToState(arkts.Global.context, state) - if (nativeModule._ContextState(arkts.Global.context) === ContextState.ES2PANDA_STATE_ERROR) { - const errorMessage = withStringResult(nativeModule._ContextErrorMessage(arkts.Global.context)) + if (state <= nativeModule._ContextState(global.context)) { + return + } + nativeModule._ProceedToState(global.context, state) + if (nativeModule._ContextState(global.context) === ContextState.ES2PANDA_STATE_ERROR) { + // TODO: maybe shoudn't do it here + nativeModule._DestroyContext(global.context) + const errorMessage = withStringResult(nativeModule._ContextErrorMessage(global.context)) if (errorMessage === undefined) { throwError(`COULDN'T GET: _ContextErrorMessage`) } @@ -48,22 +54,30 @@ export function proceedToState(state: ContextState): void { } export function startChecker(): boolean { - return nativeModule._CheckerStartChecker(arkts.Global.context) + return nativeModule._CheckerStartChecker(global.context) } -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 nodeByPeer(decl) -} +// export function getDecl(node: arkts.Node): arkts.Node | undefined { +// let decl = node.peer +// decl = nativeModule._AstNodeVariableConst(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// decl = nativeModule._VariableDeclaration(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// decl = nativeModule._DeclNode(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// return nodeByPeer(decl) +// } + +// export function getOriginalNode(node: arkts.Node): arkts.Node { +// const peer = nativeModule._AstNodeOriginalNodeConst(global.context, node.peer) +// if (peer === arkts.NULLPTR) { +// return node +// } +// return nodeByPeer(peer) +// } diff --git a/arkoala-arkts/libarkts/src/arkts/visitor.ts b/arkoala-arkts/libarkts/src/arkts/visitor.ts index fd0164fb70f8e1d8ca61a9fb087ea451d297b4e2..08136808535d0cc16cee84e1909941998f76923d 100644 --- a/arkoala-arkts/libarkts/src/arkts/visitor.ts +++ b/arkoala-arkts/libarkts/src/arkts/visitor.ts @@ -2,10 +2,10 @@ import * as arkts from "./types" import { factory } from "./factory/nodeFactory" import * as util from "./utilities" import { SyntaxKind } from "./enums" - +/* type Visitor = (node: arkts.Node) => arkts.Node -// TODO: rethink +// TODO: rethink (remove as) function nodeVisitor(node: T, visitor: Visitor): T { if (node === undefined) { return node @@ -13,12 +13,12 @@ function nodeVisitor(node: T, visitor: Visitor return visitor(node) as T } -// TODO: rethink -function nodesVisitor(nodes: arkts.NodeArray | undefined, visitor: Visitor): T[] { +// TODO: rethink (remove as) +function nodesVisitor | undefined>(nodes: TIn, visitor: Visitor): T[] | TIn { if (nodes === undefined) { - return [] + return nodes } - return nodes.map((node: T) => (visitor(node) as T)) + return nodes.map(node => visitor(node) as T) } type VisitEachChildFunction = (node: T, visitor: Visitor) => T @@ -33,6 +33,8 @@ type HasChildren = | arkts.ClassDeclaration | arkts.MethodDeclaration | arkts.Block + | arkts.VariableStatement + | arkts.VariableDeclarationList type VisitEachChildTable = { [TNode in HasChildren as TNode["kind"]]: VisitEachChildFunction } @@ -47,12 +49,12 @@ const visitEachChildTable: VisitEachChildTable = { [SyntaxKind.FunctionDeclaration]: function (node: arkts.FunctionDeclaration, visitor: Visitor) { return factory.updateFunctionDeclaration( node, - undefined, + node.modifiers, undefined, nodeVisitor(node.name, visitor), - undefined, + nodesVisitor(node.typeParameters, visitor), nodesVisitor(node.parameters, visitor), - undefined, + nodeVisitor(node.type, visitor), nodeVisitor(node.body, visitor), ) }, @@ -106,6 +108,19 @@ const visitEachChildTable: VisitEachChildTable = { nodesVisitor(node.statements, visitor), ) }, + [SyntaxKind.VariableStatement]: function (node: arkts.VariableStatement, visitor: Visitor) { + return factory.updateVariableStatement( + node, + undefined, + nodeVisitor(node.declarationList, visitor), + ) + }, + [SyntaxKind.VariableDeclarationList]: function (node: arkts.VariableDeclarationList, visitor: Visitor) { + return factory.updateVariableDeclarationList( + node, + nodesVisitor(node.declarations, visitor), + ) + }, } function nodeHasChildren(node: arkts.Node): node is HasChildren { @@ -122,3 +137,4 @@ export function visitEachChild( } return (visitFunc === undefined) ? node : visitFunc(node, visitor); } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/src/es2panda.ts b/arkoala-arkts/libarkts/src/es2panda.ts index 1040dea0dc31b9ed987189446b3902bc44a1feee..4f9f9683a86eefa50c199ef72e713bd22bef786b 100644 --- a/arkoala-arkts/libarkts/src/es2panda.ts +++ b/arkoala-arkts/libarkts/src/es2panda.ts @@ -2,7 +2,11 @@ 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" +import global from "./arkts/global" +import { + generateBin, + runAbc, +} from "../test/test-util" function parseCommandLineArgs() { const commander = new Command() @@ -25,13 +29,13 @@ function parseCommandLineArgs() { function es2panda(configPath: string, filePath: string, transform: (ast: arkts.Node) => arkts.Node) { const source = fs.readFileSync(filePath).toString() - arkts.Global.config = arkts.createConfig([ + global.config = arkts.createConfig([ '_', '--arktsconfig', configPath, filePath ]) - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, filePath) + global.context = arkts.createContextFromString(global.config, source, filePath) arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) const program = arkts.contextProgram() const ast = arkts.programAst(program) @@ -39,7 +43,8 @@ function es2panda(configPath: string, filePath: string, transform: (ast: arkts.N transform(ast) // TODO: this should be called after executing all plugins - generateBinAndRun() + generateBin() + runAbc() } function plugins(configPath: string): Promise<((ast: arkts.Node) => arkts.Node)[]> { diff --git a/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts index 7791c6af8a29d252712367fefb6428b2a4bcf91f..91662b7bc95ff90070a7620cdbc7c406dee3a59b 100644 --- a/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts @@ -1,9 +1,10 @@ +/* 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() { + test.only("updating-expression-statement", function() { const sample_in = ` function foo(lambda: (instance: string) => string): void { @@ -18,20 +19,22 @@ suite(util.getSuiteTitle(__filename), () => { const sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) util.assert(arkts.isSourceFile(sourceFile)) - const expressionStatement = sourceFile.statements[1] - util.assert(arkts.isExpressionStatement(expressionStatement)) + console.log(arkts.dumpJsonNode(sourceFile)) - const newStatements = [ - sourceFile.statements[0], - arkts.factory.updateExpressionStatement( - expressionStatement, - expressionStatement.expression - ) - ] + // const expressionStatement = sourceFile.statements[1] + // util.assert(arkts.isExpressionStatement(expressionStatement)) - arkts.factory.updateSourceFile(sourceFile, newStatements) + // const newStatements = [ + // sourceFile.statements[0], + // arkts.factory.updateExpressionStatement( + // expressionStatement, + // expressionStatement.expression + // ) + // ] + + // arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + // util.assertEqualsBinaryOuptut('ABC', this) }) test("updating-function-declaration", function() { @@ -69,10 +72,9 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + util.assertEqualsBinaryOuptut('A', this) }) - // failing now test("updating-lambda-call", function() { const sample_in = ` @@ -117,6 +119,7 @@ suite(util.getSuiteTitle(__filename), () => { ] arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + util.assertEqualsBinaryOuptut('', this) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts b/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e1df89b02423f3d2ff16213008a3721551dd2c40 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts @@ -0,0 +1,38 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { AnalysisVisitor } from "../../compatible/src/analysis-visitor" +import { Tracer } from "../../compatible/src/util" +import { Rewrite } from "../../compatible/src/transformation-context" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + const _memo_x: string = "A" + + function _memo_foo() {} + + _memo_foo() + ` + + util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const options = {} + + const tracer = new Tracer(options) + const rewrite = new Rewrite(sourceFile, options) + + sourceFile = new AnalysisVisitor(tracer, rewrite).visitor(sourceFile) + + util.assert(rewrite.functionTable.size === 1) + util.assert(rewrite.callTable.size === 1) + util.assert(rewrite.variableTable.size === 1) + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/basic.test.ts b/arkoala-arkts/libarkts/test/es2panda/basic.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..73d9e448ee558218a879783423d02d9e3c57d020 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/basic.test.ts @@ -0,0 +1,168 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { factory } from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + ` + + let sourceFile = arkts.factory.createSourceFile(sample_in) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + arkts.factory.createExpressionStatement( + arkts.factory.createIdentifier("abc") + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + abc + ` + ) + }) + + test("sample-2", function() { + const sample_in = + ` + ` + + let sourceFile = arkts.factory.createSourceFile(sample_in) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + arkts.factory.createFunctionDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("test"), + undefined, + [], + undefined, + arkts.factory.createBlock( + [], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test() {} + ` + ) + }) + + test("sample-3", function() { + const sample_in = + ` + ` + + let sourceFile = factory.createSourceFile(sample_in) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.createFunctionDeclaration( + undefined, + undefined, + factory.createIdentifier("test"), + undefined, + [ + factory.createParameterDeclaration( + undefined, + undefined, + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + undefined + ) + ], + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createBlock( + [ + factory.createReturnStatement( + factory.createNumericLiteral("0") + ) + ], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test(x: string): number { + return 0; + } + ` + ) + }) + + test("sample-4", function() { + const sample_in = + ` + ` + + let sourceFile = factory.createSourceFile(sample_in) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.createFunctionDeclaration( + undefined, + undefined, + factory.createIdentifier("test"), + [ + factory.createTypeParameterDeclaration( + undefined, + factory.createIdentifier("T"), + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + undefined + ) + ], + [ + factory.createParameterDeclaration( + undefined, + undefined, + factory.createIdentifier("x"), + undefined, + factory.createTypeReferenceNode( + factory.createIdentifier("T"), + undefined + ), + undefined + ) + ], + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + factory.createBlock( + [ + factory.createReturnStatement( + factory.createStringLiteral("aaa") + ) + ], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test(x: T): string { + return "aaa" + } + ` + ) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts index 3de1f3019dbb4299a2ff0f085e104409e922a169..4fa6c351a95096e6186f3e25d2da57533aa3dc8d 100644 --- a/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { BuilderLambdaTransformer } from "../../compatible/src/builder-lambda-transformer" @@ -68,12 +69,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` _Foo(((instance: string) => {}), "label") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -143,14 +144,14 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` _Foo(((instance: string) => { instance.bar().qux(); }), "label1", "label2") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -173,14 +174,14 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` foo(((instance: string) => { return instance; }), "label") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -203,14 +204,14 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` foo(((instance: string) => { return instance.bar().qux(); }), "label1", "label2") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -241,9 +242,8 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function Foo(builder: ((instance: string)=> string), arg1: string): void { console.log(((arg1) + (builder("ABC")))); @@ -252,7 +252,9 @@ suite(util.getSuiteTitle(__filename), () => { Foo(((instance: string) => { return instance.charAt(1); }), "> second_char_of_ABC: ") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) }) +*/ \ No newline at end of file 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 e9c926481e5c185a827f996f3024cb87423899d5..dc8eb00a07dc43dc96ff2f89bd561a3f69b09238 100644 --- a/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts @@ -9,9 +9,7 @@ suite(util.getSuiteTitle(__filename), () => { const sample_in = `` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcDecl = arkts.factory.createFunctionDeclaration( @@ -34,23 +32,19 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function test_func() {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) test("empty-function-with-param", function() { - // function test_func(x: long) { - // // empty - // } - - util.getDefaultSetup('') + const sample_in = `` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcParams = [ @@ -59,7 +53,7 @@ suite(util.getSuiteTitle(__filename), () => { undefined, arkts.factory.createIdentifier("x"), undefined, - arkts.factory.createEtsPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_INT), + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), undefined ) ] @@ -83,12 +77,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - function test_func(x: long) {} ` + function test_func(x: number) {} + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -97,9 +91,9 @@ suite(util.getSuiteTitle(__filename), () => { // // empty // } - util.getDefaultSetup('') + const sample_in = `` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcParams = [ @@ -132,37 +126,164 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function test_func(x: string) {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) - test("async-empty-function", function() { - // async function test_func() {} + // test("async-empty-function", function() { + // // async function test_func() {} + + // const sample_in = `` + + // util.getDefaultSetup(sample_in) + + // let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + // util.assert(arkts.isSourceFile(sourceFile)) + + // const funcDecl = arkts.factory.createFunctionDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.AsyncKeyword) + // ], + // undefined, + // arkts.factory.createIdentifier("test_func"), + // undefined, + // [], + // undefined, + // arkts.factory.createBlock( + // [], + // true + // ) + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // funcDecl + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // async function test_func() {} + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + // test("empty-method-with-public-static-modifiers", function() { + // // class A { + // // static test_func() { + // // } + // // } + + // const sample_in = + // ` + // class A { + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let classDecl = sourceFile.statements[0] + // util.assert(arkts.isClassDeclaration(classDecl)) + + // classDecl = arkts.factory.updateClassDeclaration( + // classDecl, + // undefined, + // arkts.factory.createIdentifier("A"), + // undefined, + // undefined, + // [ + // arkts.factory.createMethodDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword), + // arkts.factory.createToken(arkts.SyntaxKind.StaticKeyword) + // ], + // undefined, + // arkts.factory.createIdentifier("test_func"), + // undefined, + // undefined, + // [], + // undefined, + // arkts.factory.createBlock( + // [], + // false + // ) + // ), + // arkts.factory.createConstructorDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword) + // ], + // [], + // arkts.factory.createBlock( + // [], + // false + // ) + // ) + // ] + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // classDecl + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // class A { + // public static test_func() {} + + // public constructor() {} + + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + test("function-with-type-parameters", function() { + // function test_func(): void {} - const sample_in = `` - - util.getDefaultSetup(sample_in) + const sample_in = + ` + ` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcDecl = arkts.factory.createFunctionDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.AsyncKeyword) - ], undefined, - arkts.factory.createIdentifier("test_func"), undefined, + arkts.factory.createIdentifier("test_func"), + [ + arkts.factory.createTypeParameterDeclaration( + undefined, + arkts.factory.createIdentifier("T"), + undefined, + undefined + ), + arkts.factory.createTypeParameterDeclaration( + undefined, + arkts.factory.createIdentifier("K"), + undefined, + undefined + ) + ], [], - undefined, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.VoidKeyword), arkts.factory.createBlock( - [], - true + [], + true ) ) @@ -173,89 +294,142 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - async function test_func() {} ` + function test_func(): void {} + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) - test("empty-method-with-public-static-modifiers", function() { - // class A { - // static test_func() { - // } - // } - + // // TODO: change 0 -> 777 (waiting fix) + // test("sample-1", function() { + // const sample_in = + // ` + // console.log("OK") + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // const funcDecl = arkts.factory.createFunctionDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("foo"), + // undefined, + // [ + // arkts.factory.createParameterDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("x"), + // undefined, + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + // arkts.factory.createNumericLiteral("0") + // ), + // arkts.factory.createParameterDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("y"), + // undefined, + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + // arkts.factory.createStringLiteral("abc") + // ) + // ], + // arkts.factory.createUnionTypeNode([ + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + // ]), + // arkts.factory.createBlock( + // [arkts.factory.createReturnStatement(arkts.factory.createBinaryExpression( + // arkts.factory.createIdentifier("x"), + // arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + // arkts.factory.createIdentifier("y") + // ))], + // true + // ) + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // funcDecl, + // sourceFile.statements[0] + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // function foo(x: number = 0, y: string = "abc"): number | string { + // return x + y + // } + // console.log("OK") + // ` + // ) + // }) + + // TODO: change 0 -> 777 (waiting fix) + test("sample-2", function() { const sample_in = ` - class A { - } + // console.log("OK") ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let classDecl = sourceFile.statements[0] - util.assert(arkts.isClassDeclaration(classDecl)) - - classDecl = arkts.factory.updateClassDeclaration( - classDecl, + const funcDecl = arkts.factory.createFunctionDeclaration( undefined, - arkts.factory.createIdentifier("A"), undefined, + arkts.factory.createIdentifier("foo"), undefined, [ - arkts.factory.createMethodDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword), - arkts.factory.createToken(arkts.SyntaxKind.StaticKeyword) - ], - undefined, - arkts.factory.createIdentifier("test_func"), + arkts.factory.createParameterDeclaration( undefined, undefined, - [], + arkts.factory.createIdentifier("x"), undefined, - arkts.factory.createBlock( - [], - false - ) + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + arkts.factory.createNumericLiteral("0") ), - arkts.factory.createConstructorDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword) - ], - [], - arkts.factory.createBlock( - [], - false - ) + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("y"), + undefined, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + arkts.factory.createStringLiteral("abc") ) - ] + ], + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + arkts.factory.createBlock( + [ + arkts.factory.createReturnStatement( + arkts.factory.createIdentifier("x") + ) + ], + true + ) ) sourceFile = arkts.factory.updateSourceFile( sourceFile, [ - classDecl + funcDecl, + // sourceFile.statements[0] ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` - class A { - public static test_func() {} - - public constructor() {} - + function foo(x: number = 0, y: string = "abc"): number { + return x } - ` + // console.log("OK") + `, + arkts.ContextState.ES2PANDA_STATE_PARSED ) }) }) diff --git a/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts index 0c44412602ca3e7d2a67b0a3649d6536943628aa..bc7d406c2e810553470c35f1d825ae18c1484cd0 100644 --- a/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { FunctionTransformer } from "../../compatible/src/function-transformer" @@ -43,3 +44,4 @@ suite(util.getSuiteTitle(__filename), () => { // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/import.test.ts b/arkoala-arkts/libarkts/test/es2panda/import.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f08f11cd1decd8760a2a649c939e2550f225c6b7 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/import.test.ts @@ -0,0 +1,63 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + // TODO: doesn't running now, but compiles (config gets only one file) + test("sample-1", function() { + const sample_in = + ` + import { TEST } from "./export" + console.log(TEST) + ` + + // util.getDefaultSetup(sample_in) + + // util.generateBinAndRun() + }) + + test("sample-2", function() { + const sample_in = + ` + import { power as F } from "std/math" + console.log(F(2, 10)) + ` + + // util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + // const classDecl = arkts.nodeByPeer(util.getStatement(1)) + // util.assert(arkts.isClassDeclaration(classDecl)) + + // const method = classDecl.members[1] + // util.assert(arkts.isMethodDeclaration(method)) + + // const body = method.body! + // util.assert(arkts.isBlock(body)) + + // const exprStatement = body.statements[0] + // util.assert(arkts.isExpressionStatement(exprStatement)) + + // const callExpr = exprStatement.expression + // util.assert(arkts.isCallExpression(callExpr)) + + // const F = callExpr.arguments[0] + // util.assert(arkts.isCallExpression(F)) + + // const ident = F.expression + // util.assert(arkts.isIdentifier(ident)) + + // console.log(arkts.dumpJsonNode(ident)) + + // const decl = arkts.getDecl(ident) + // if (decl !== undefined) { + // console.log(arkts.dumpJsonNode(decl)) + // } else { + // console.log(decl) + // } + + // util.generateBinAndRun() + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts index decf399ba99d2c6ba1782251e47d2902b2caebf8..b99f10ecfe331afa4da2769929ea944835b99a83 100644 --- a/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" @@ -66,13 +67,16 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ) ] testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) const newLambdaParams = [ arkts.factory.createParameterDeclaration( @@ -136,9 +140,8 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` 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) { @@ -147,7 +150,9 @@ suite(util.getSuiteTitle(__filename), () => { content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); return __memo_scope.recache(); } - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts b/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8ad9478304794b06c3fda786a7a1696cc327a08d --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts @@ -0,0 +1,121 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { factory } from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + // TODO: change 0 -> 777 (waiting fix) + test("const-number", function() { + const sample_in = + ` + function f() {} + ` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varDecl = factory.createVariableStatement( + undefined, + factory.createVariableDeclarationList( + [factory.createVariableDeclaration( + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createNumericLiteral("0") + )] + ) + ) + + const f = sourceFile.statements[0] + util.assert(arkts.isFunctionDeclaration(f)) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.updateFunctionDeclaration( + f, + f.modifiers, + undefined, + f.name, + f.typeParameters, + f.parameters, + f.type, + factory.createBlock([ + varDecl + ]) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function f() { + const x: number = 0 + } + ` + ) + }) + + test("declaration-list", function() { + // const x: number = 0, y: string = "a", z = 0 + + const sample_in = `const x = 1` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varStatement = sourceFile.statements[0] + util.assert(arkts.isVariableStatement(varStatement)) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + factory.updateVariableStatement( + varStatement, + [ + // TODO: not ok maybe (not my fault) + factory.createToken(arkts.SyntaxKind.PublicKeyword), + factory.createToken(arkts.SyntaxKind.StaticKeyword), + factory.createToken(arkts.SyntaxKind.ConstKeyword), + ], + factory.createVariableDeclarationList( + [ + factory.createVariableDeclaration( + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createNumericLiteral("0") + ), + factory.createVariableDeclaration( + factory.createIdentifier("y"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + factory.createStringLiteral("a") + ), + factory.createVariableDeclaration( + factory.createIdentifier("z"), + undefined, + undefined, + factory.createNumericLiteral("0") + ) + ], + undefined + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + const x: number = 0, y: string = "a", z = 0 + ` + ) + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts index de19f47f37f738581a8f2c23b586df55f3b418b7..ba23e21cd6f3bae289168fe40031fd5e659add60 100644 --- a/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { MemoTransformer } from "../../compatible/src/memo-transformer" @@ -25,3 +26,4 @@ suite(util.getSuiteTitle(__filename), () => { // console.log(arkts.dumpSrcNode(sourceFile)) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts index e38afc82ce0a0d0094115bedddd71ddddfabb069..151267112e9bc0e26879eccf802c8d6419907a39 100644 --- a/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import * as util from "../test-util" import { PrintVisitor } from "../../compatible/src/print-visitor" @@ -24,38 +25,41 @@ suite(util.getSuiteTitle(__filename), () => { ` const expected = ` - SourceFile (mod: 0) - ClassDeclaration (mod: 5) - Identifier (mod: 0) - PropertyDeclaration (mod: 4) - MethodDeclaration (mod: 4) - Identifier (mod: 0) - Block (mod: 0) - ExpressionStatement (mod: 0) - UnsupportedNode (mod: 0) - MethodDeclaration (mod: 0) - Identifier (mod: 0) - Block (mod: 0) - ClassDeclaration (mod: 5) - Identifier (mod: 0) - MethodDeclaration (mod: 0) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - VariableStatement (mod: 0) - ExpressionStatement (mod: 0) - CallExpression (mod: 0) - PropertyAccessExpression (mod: 0) - Identifier (mod: 0) - Identifier (mod: 0) + SourceFile (mods: []) + ClassDeclaration (mods: [1,4]) + Identifier (mods: []) + PropertyDeclaration (mods: [4]) + MethodDeclaration (mods: [4]) + Identifier (mods: []) + Block (mods: []) + ExpressionStatement (mods: []) + AssignmentExpression (mods: []) + MethodDeclaration (mods: []) + Identifier (mods: []) + Block (mods: []) + ClassDeclaration (mods: [1,4]) + Identifier (mods: []) + MethodDeclaration (mods: []) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + ETSPrimitiveType (mods: []) + Block (mods: []) + VariableStatement (mods: []) + VariableDeclarationList (mods: []) + VariableDeclaration (mods: []) + ExpressionStatement (mods: []) + CallExpression (mods: []) + PropertyAccessExpression (mods: []) + Identifier (mods: []) + Identifier (mods: []) ` util.getDefaultSetup(source) @@ -66,3 +70,4 @@ suite(util.getSuiteTitle(__filename), () => { util.assert.equal(util.alignText(output), util.alignText(expected)) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts b/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c85a28a2b597f56dcf5c4c118ac8cddae7b09669 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts @@ -0,0 +1,56 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + class A {} + + let x: AB + + console.log("ok") + ` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varDecl = sourceFile.statements[1] + util.assert(arkts.isVariableStatement(varDecl)) + + const declList = varDecl.declarationList + util.assert(arkts.isVariableDeclarationList(declList)) + + const x = declList.declarations[0] + util.assert(arkts.isVariableDeclaration(x)) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + sourceFile.statements[0], + arkts.factory.updateVariableStatement( + varDecl, + undefined, + // declList + arkts.factory.createVariableDeclarationList( + [arkts.factory.createVariableDeclaration( + arkts.factory.createIdentifier("x"), + undefined, + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("A") + ), + undefined + )] + ) + ), + sourceFile.statements[2] + ] + ) + + util.assertEqualsBinaryOuptut('ok', this) + }) +}) +*/ \ No newline at end of file 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 7755959f79feb8b2066b69b1959e0a2f0d3b5edb..77b384bec3f789d2bfa2ada17ab1330b535f2c44 100644 --- a/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts @@ -15,9 +15,7 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) let testFunc = sourceFile.statements[0] @@ -51,9 +49,8 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function new_test_func(x: number, y: string) {} ` @@ -73,12 +70,10 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) @@ -91,12 +86,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, x: number) {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -108,18 +103,17 @@ suite(util.getSuiteTitle(__filename), () => { const sample_in = ` - function foo() { + function foo(x: string) { // empty } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -148,12 +142,11 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` - function foo() { - x; + function foo(x: string) { + x } ` ) @@ -172,13 +165,12 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -212,23 +204,20 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo() { __memo_scope.recache; } - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) // 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() // } @@ -239,13 +228,12 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -254,7 +242,9 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ) ] @@ -281,196 +271,195 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo() { return __memo_scope.recache(); } - ` - ) - }) - - // 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 sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) - util.assert(arkts.isSourceFile(sourceFile)) - - let testFunc = arkts.nodeByPeer(util.getStatement(0)) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - let body_statements = [ - arkts.factory.createIfStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("unchanged") - ), - arkts.factory.createBlock([ - 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.assert(arkts.isFunctionDeclaration(testFunc)) - - sourceFile = arkts.factory.updateSourceFile( - sourceFile, - [ - testFunc - ] - ) - - util.assertAstEqualsAfter( - sourceFile, + `, arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - function foo() { - if (__memo_scope.unchanged) { - return __memo_scope.cached; - } - } - ` ) }) - // 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 sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) - util.assert(arkts.isSourceFile(sourceFile)) - - let testFunc = arkts.nodeByPeer(util.getStatement(0)) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - let body_statements = [ - arkts.factory.createIfStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("unchanged") - ), - arkts.factory.createBlock([ - 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) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - testFunc = arkts.factory.updateFunctionDeclaration( - testFunc, - undefined, - undefined, - testFunc.name, - undefined, - testFunc.parameters, - undefined, - arkts.factory.updateBlock( - testFunc.body, - body_statements - ) - ) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - sourceFile = arkts.factory.updateSourceFile( - sourceFile, - [ - testFunc - ] - ) - - util.assertAstEqualsAfter( - sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - 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(); - } - ` - ) - }) + // // body memo rewrite (adding if statement) + // test("add-if-statement-to-function-body", function() { + // // function foo() { + // // if (__memo_scope.unchanged) + // // return __memo_scope.cached + // // } + + // const sample_in = + // ` + // function foo() { + // // empty + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let testFunc = sourceFile.statements[0] + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // let body_statements = [ + // arkts.factory.createIfStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("unchanged") + // ), + // arkts.factory.createBlock([ + // 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.assert(arkts.isFunctionDeclaration(testFunc)) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // testFunc + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // function foo() { + // if (__memo_scope.unchanged) { + // return __memo_scope.cached; + // } + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + // // 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 + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let testFunc = sourceFile.statements[0] + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // let body_statements = [ + // arkts.factory.createIfStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("unchanged") + // ), + // arkts.factory.createBlock([ + // 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") + // ), + // undefined, + // undefined + // ) + // ), + // ...testFunc.body.statements + // ] + + // testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // testFunc = arkts.factory.updateFunctionDeclaration( + // testFunc, + // undefined, + // undefined, + // testFunc.name, + // undefined, + // testFunc.parameters, + // undefined, + // arkts.factory.updateBlock( + // testFunc.body, + // body_statements + // ) + // ) + // util.assert(arkts.isFunctionDeclaration(testFunc)) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // testFunc + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // 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(); + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) }) diff --git a/arkoala-arkts/libarkts/test/test-util.ts b/arkoala-arkts/libarkts/test/test-util.ts index 55f12bc4a3abf5748059abcff4f23d223859f319..4148c831d5b835e9b6592c3a9efcfbbabf180652 100644 --- a/arkoala-arkts/libarkts/test/test-util.ts +++ b/arkoala-arkts/libarkts/test/test-util.ts @@ -14,26 +14,18 @@ */ import * as arkts from "../src/arkts" +import * as ets from "../src/arkts/typesEts" import * as path from "path" import { KNativePointer } from "@koalaui/interop" import { nativeModule } from "../src/NativeModule" import { NativePtrDecoder } from "../src/node/Platform" import { assert } from "chai" -import { PrintVisitor } from "../compatible/src/print-visitor" +// import { PrintVisitor } from "../compatible/src/print-visitor" +import { exec } from "child_process" +import global from "../src/arkts/global" -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 (!arkts.Global.isInitializedConfig()) { - arkts.Global.config = arkts.createConfig(DefaultConfig.config) - } - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, DefaultConfig.sourceFile) - arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) -} +export { nativeModule } from "../src/NativeModule" +export { assert } from "chai" class defaultTransformationContext implements arkts.TransformationContext { } @@ -42,13 +34,6 @@ export function getDefaultTransformationContext(): arkts.TransformationContext { return new defaultTransformationContext() } -export class AstProvider { - public static provideAst(): KNativePointer { - const program = arkts.contextProgram() - return arkts.programAst(program).peer - } -} - export function alignText(text: string): string { const lines = text.replace(/\t/gy, ' ').split('\n') @@ -69,45 +54,55 @@ export function alignText(text: string): string { return lines.map(str => str.slice((shift === -1) ? 0 : shift)).join('\n').trim() } -export function printVisitorOutput(node: arkts.Node): string { - return (new PrintVisitor(getDefaultTransformationContext())).astToString(node) -} - -export function getStatement(index: number): KNativePointer { - const peer = AstProvider.provideAst() - return (new NativePtrDecoder()).decode(nativeModule._BlockStatementStatements(arkts.Global.context, peer))[index] -} +// export function printVisitorOutput(node: arkts.Node): string { +// return (new PrintVisitor(getDefaultTransformationContext())).astToString(node) +// } export function getSuiteTitle(fileName: string) { return path.basename(fileName).split('.')[0] } -export function assertEqualsSource(sourceResult: string, sourceExpect: string) { +export function assertEqualsSource(sourceResult: string, sourceExpect: string, message?: 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') + sourceExpect.trim().split('\n').map((line: string) => line.trim()).join('\n'), + message ) } -export function assertAstEqualsAfter(node: arkts.Node, state: arkts.ContextState, source: string) { - const ast = arkts.dumpJsonNode(node) - const src = arkts.dumpSrcNode(node) - const mods = arkts.dumpModifiers(node.peer) - - const _oldContext = arkts.Global.context - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, DefaultConfig.sourceFile) - arkts.proceedToState(state) - const peer = AstProvider.provideAst() - arkts.Global.context = _oldContext - - assert.equal(ast, arkts.dumpJson(peer)) - assertEqualsSource(src, arkts.dumpSrcNode(arkts.nodeByPeer(peer))) - assert.equal(mods, arkts.dumpModifiers(peer)) +export function assertEqualsAfter(node: arkts.SourceFile, source: string, state?: arkts.ContextState) { + const finalState: arkts.ContextState = (() => { + if (state !== undefined) { + return state + } + if (process.env.STATE_CHECKED !== undefined) { + return arkts.ContextState.ES2PANDA_STATE_CHECKED + } + return arkts.ContextState.ES2PANDA_STATE_PARSED + })() + + arkts.proceedToState(finalState) + + const ast = node._node.dumpJson() + const src = node._node.dumpSrc() + const mods = node._node.dumpModifierFlags() + + nativeModule._DestroyContext(global.context) + const sourceFile = arkts.factory.createSourceFile(source) + arkts.proceedToState(finalState) + const root = sourceFile._node + try { + assert.equal(ast, root.dumpJson(), 'Error on JSON comparison') + assertEqualsSource(src, root.dumpSrc(), 'Error on SOURCE comparison') + assert.equal(mods, root.dumpModifierFlags(), 'Error on MODIFIERS comparison') + } finally { + nativeModule._DestroyContext(global.context) + } } -export function dumpFirst() { - return arkts.dumpJson(getStatement(0)) -} +// export function dumpFirst() { +// return arkts.dumpJson(getStatement(0)) +// } export function addMemoParamsToFunctionDeclaration(func: arkts.FunctionDeclaration): arkts.FunctionDeclaration { return arkts.factory.updateFunctionDeclaration( @@ -144,15 +139,17 @@ export function addMemoParamsToFunctionDeclaration(func: arkts.FunctionDeclarati ) } -export function generateBinAndRun() { +export function generateBin(): void { 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') +} + +export function runAbc(): void { exec( 'npm run run:abc', - (err: any, stdout: any, stderr: any) => { - if (err) { + (error: any, stdout: string, stderr: string) => { + if (error) { console.log('failed to run abc') return; } @@ -162,5 +159,31 @@ export function generateBinAndRun() { ) } -export { nativeModule } from "../src/NativeModule" -export { assert } from "chai" +export function assertEqualsBinaryOuptut(output: string, ctx: Mocha.Context): void { + if (process.env.TEST_BIN === undefined) { + ctx.skip() + } + try { + generateBin() + exec( + 'npm run run:abc', + (error: any, stdout: string, stderr: string) => { + if (error) { + console.log('failed to run abc') + return; + } + const lines = stdout.trim().split('\n') + assert(lines.length >= 2) + assert.equal(lines[0], '> run:abc') + assert.equal(stderr, '') + if (lines.length === 2) { + assert.equal('', output.trim()) + } else { + assert.equal(lines.splice(2).join('\n').trim(), output.trim()) + } + } + ) + } finally { + nativeModule._DestroyContext(global.context) + } +} diff --git a/incremental/compiler-plugin/.gitlab-ci.yml b/incremental/compiler-plugin/.gitlab-ci.yml index a99749601bd8f0df4babcacddedf4239cde1cc84..0e816c80b66ae0dce410def90dea4817657fab09 100644 --- a/incremental/compiler-plugin/.gitlab-ci.yml +++ b/incremental/compiler-plugin/.gitlab-ci.yml @@ -12,7 +12,7 @@ # limitations under the License. build compiler-plugin: - stage: build-compiler + stage: build interruptible: true extends: .linux-vm-shell-task before_script: @@ -41,4 +41,3 @@ test compiler-plugin: - build compat - build common - build compiler-plugin -