From d214a8b0d37db1c4cdb989f950e5dc6e8f3435b5 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 24 Sep 2021 10:53:36 +0800 Subject: [PATCH 01/39] Add basic infrastructure of typeinfo recorder Change-Id: I637953d0be0baa34fb8f32d6070ce158f9e91aa6 Signed-off-by: zhuoli --- ts2panda/src/recorder.ts | 1 + ts2panda/src/typeRecorder.ts | 56 +++++++++++++++++++++++++++++++ ts2panda/src/variable.ts | 12 +++++++ ts2panda/templates/irnodes.ts.erb | 9 +++++ 4 files changed, 78 insertions(+) create mode 100644 ts2panda/src/typeRecorder.ts diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c..eb1761116c 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -62,6 +62,7 @@ export class Recorder { private importStmts: Array = []; private exportStmts: Array = []; private defaultUsed: boolean = false; + private recordTypeContent: boolean = false; constructor(node: ts.Node, scope: Scope, compilerDriver: CompilerDriver) { this.node = node; diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts new file mode 100644 index 0000000000..e150ca60ee --- /dev/null +++ b/ts2panda/src/typeRecorder.ts @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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. + */ + +export enum PremitiveType { + UNDEFINED, + STRING, + NUMBER, + BOOLEAN, + _LENGTH +} + +export class TypeRecorder { + private type2Index: Map = new Map(); + private typeInfo: Array; + private index: number; + + constructor() { + this.index = PremitiveType._LENGTH; + } + + setType2Index(typePosition: string) { + this.type2Index.set(typePosition, this.index); + } + + setTypeInfo(typeContent: any) { + this.typeInfo[this.index] = typeContent; + } + + addType(typePosition: string, typeContent: any) { + this.setType2Index(typePosition); + this.setTypeInfo(typeContent); + this.index += this.index; + } + + getType2Index(): Map { + return this.type2Index; + } + + getTypeInfo(): Array { + return this.typeInfo; + } + + +} \ No newline at end of file diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 966cb9191b..60226e2b72 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -19,6 +19,7 @@ import { LoopScope, VariableScope } from "./scope"; +import { PremitiveType } from "./typeinfo" export enum VarDeclarationKind { NONE, @@ -33,6 +34,7 @@ export enum VarDeclarationKind { export abstract class Variable { private vreg: VReg | undefined; private name: string; + private typeIndex: number; isLexVar: boolean = false; idxLex: number = 0; constructor( @@ -42,10 +44,12 @@ export abstract class Variable { this.name = name; this.vreg = undefined; this.name = name; + this.typeIndex = PremitiveType.UNDEFINED; } bindVreg(vreg: VReg) { this.vreg = vreg; + this.vreg.setType(this.typeIndex); } hasAlreadyBinded(): boolean { @@ -63,6 +67,14 @@ export abstract class Variable { return this.name; } + getTypeIndex() { + return this.typeIndex; + } + + setTypeIndex(typeIndex: number) { + return this.typeIndex = typeIndex; + } + setLexVar(scope: VariableScope | LoopScope) { this.idxLex = scope.getLexVarIdx() scope.pendingCreateEnv(); diff --git a/ts2panda/templates/irnodes.ts.erb b/ts2panda/templates/irnodes.ts.erb index 40e6936c0e..eb8bb5f89e 100755 --- a/ts2panda/templates/irnodes.ts.erb +++ b/ts2panda/templates/irnodes.ts.erb @@ -185,6 +185,7 @@ export abstract class Intrinsic extends IRNode { export class VReg { private static global_id = 0; + private typeIndex: number; readonly id: number; // used for debug purpose to distinguish one instance from another num: number = -1; @@ -225,6 +226,14 @@ export class VReg { return; } } + + getTypeIndex() { + return this.typeIndex; + } + + setTypeIndex(typeIndex: number) { + this.typeIndex = typeIndex; + } } export class Imm extends IRNode { -- Gitee From 9f4a5d268edddabd4fbb20eb35aff0ca2de25eb2 Mon Sep 17 00:00:00 2001 From: ctw Date: Fri, 24 Sep 2021 10:48:33 +0800 Subject: [PATCH 02/39] build infastructure of typeSystem Signed-off-by: ctw Change-Id: Ice89e1b4b9ece6ab527192d9c115b7ba56f6b3d7 --- ts2panda/src/base/typeSystem.ts | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 ts2panda/src/base/typeSystem.ts diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts new file mode 100644 index 0000000000..adff14a875 --- /dev/null +++ b/ts2panda/src/base/typeSystem.ts @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ts from "typescript"; + +abstract class BaseType { + +} + +export class ClassType extends BaseType { + modifier: number = 0; // 0 -> unabstract, 1 -> abstract; + heritages: Array = new Array(); + unstaticFields: Map = new Map(); + staticFields: Map = new Map(); + unstaticMethods: Array = new Array(); + staticMethods: Array = new Array(); + + constructor(classNode: ts.ClassDeclaration) { + super(); + + if (classNode.AbstractKeyword) { + this.modifier = 1; + } + + // pls extract class info here; + } + + extractFields() { + + } + +} + +export class FunctionType extends BaseType { + modifier: number = 0; // 0 -> normal function or method, 1 -> static member of class + name: string = ''; + parameters: Map = new Map(); + returnType: number = 0; + + constructor(funcNode: ts.FunctionLikeDeclaration) { + super(); + + if (funcNode.AbstractKeyword) { + this.modifier = 1; + } + + // pls extract function info here + } + +} \ No newline at end of file -- Gitee From f0ffd233bf57d94259b5612c15c884f15008a25b Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 24 Sep 2021 17:00:33 +0800 Subject: [PATCH 03/39] modify public/static modifier for classType & functionType Change-Id: Ia12d8b868ef6d46f037d3224c9aa75506aff9624 --- ts2panda/src/base/typeSystem.ts | 129 +++++++++++++++++--------------- ts2panda/src/typeRecorder.ts | 107 +++++++++++++------------- 2 files changed, 120 insertions(+), 116 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index adff14a875..a50404a26b 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -1,62 +1,69 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as ts from "typescript"; - -abstract class BaseType { - -} - -export class ClassType extends BaseType { - modifier: number = 0; // 0 -> unabstract, 1 -> abstract; - heritages: Array = new Array(); - unstaticFields: Map = new Map(); - staticFields: Map = new Map(); - unstaticMethods: Array = new Array(); - staticMethods: Array = new Array(); - - constructor(classNode: ts.ClassDeclaration) { - super(); - - if (classNode.AbstractKeyword) { - this.modifier = 1; - } - - // pls extract class info here; - } - - extractFields() { - - } - -} - -export class FunctionType extends BaseType { - modifier: number = 0; // 0 -> normal function or method, 1 -> static member of class - name: string = ''; - parameters: Map = new Map(); - returnType: number = 0; - - constructor(funcNode: ts.FunctionLikeDeclaration) { - super(); - - if (funcNode.AbstractKeyword) { - this.modifier = 1; - } - - // pls extract function info here - } - +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ts from "typescript"; + +export enum PremitiveType { + UNDEFINED, + STRING, + NUMBER, + BOOLEAN, + _LENGTH +} + +export abstract class BaseType { + +} + +export class ClassType extends BaseType { + modifier: number = 0; // 0 -> unabstract, 1 -> abstract; + heritages: Array = new Array(); + fields : Map> = new Map>(); // Array: [type][static][public/private] + Methods: Array = new Array(); + + constructor(classNode: ts.ClassDeclaration) { + super(); + + if (classNode.AbstractKeyword) { + this.modifier = 1; + } + + // pls extract class info here; + } + + extractFields() { + + } + +} + +export class FunctionType extends BaseType { + modifierPublic: number = 0; + modifierStatic: number = 0; // 0 -> normal function or method, 1 -> static member of class + name: string = ''; + parameters: Map = new Map(); + returnType: number = 0; + + constructor(funcNode: ts.FunctionLikeDeclaration) { + super(); + + if (funcNode.AbstractKeyword) { + this.modifier = 1; + } + + // pls extract function info here + } + } \ No newline at end of file diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index e150ca60ee..940757a69f 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -1,56 +1,53 @@ -/* - * Copyright (c) 2021 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. - */ - -export enum PremitiveType { - UNDEFINED, - STRING, - NUMBER, - BOOLEAN, - _LENGTH -} - -export class TypeRecorder { - private type2Index: Map = new Map(); - private typeInfo: Array; - private index: number; - - constructor() { - this.index = PremitiveType._LENGTH; - } - - setType2Index(typePosition: string) { - this.type2Index.set(typePosition, this.index); - } - - setTypeInfo(typeContent: any) { - this.typeInfo[this.index] = typeContent; - } - - addType(typePosition: string, typeContent: any) { - this.setType2Index(typePosition); - this.setTypeInfo(typeContent); - this.index += this.index; - } - - getType2Index(): Map { - return this.type2Index; - } - - getTypeInfo(): Array { - return this.typeInfo; - } - - +/* + * Copyright (c) 2021 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 { + BaseType, + PremitiveType +} from "./base/typeSystem"; + +export class TypeRecorder { + private type2Index: Map = new Map(); + private typeInfo: Array = new Array(); + private index: number; + + constructor() { + this.index = PremitiveType._LENGTH; + } + + setType2Index(typePosition: string) { + this.type2Index.set(typePosition, this.index); + } + + setTypeInfo(typeInfo: BaseType) { + this.typeInfo[this.index] = typeInfo; + } + + addType(typePosition: string, typeInfo: BaseType) { + this.setType2Index(typePosition); + this.setTypeInfo(typeInfo); + this.index += this.index; + } + + getType2Index(): Map { + return this.type2Index; + } + + getTypeInfo(): Array { + return this.typeInfo; + } + + } \ No newline at end of file -- Gitee From be70fc83e50df9c6d85d1303c4ac04d76f7a4043 Mon Sep 17 00:00:00 2001 From: ctw Date: Fri, 24 Sep 2021 17:38:43 +0800 Subject: [PATCH 04/39] 1. Add typeArrayBuffer to store all the typeInfo 2. Add vreg-type binding field to function structure Change-Id: I9c579da7d9f8ee7473d7cab740c5c8668143873e Signed-off-by: ctw --- ts2panda/src/base/typeSystem.ts | 15 +++++++++++++-- ts2panda/src/pandagen.ts | 24 ++++++++++++++++++++++++ ts2panda/src/pandasm.ts | 3 +++ ts2panda/src/ts2panda.ts | 7 +++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index a50404a26b..f163115a66 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -14,6 +14,7 @@ */ import * as ts from "typescript"; +import { Literal, LiteralBuffer } from "./literal"; export enum PremitiveType { UNDEFINED, @@ -24,7 +25,7 @@ export enum PremitiveType { } export abstract class BaseType { - + abstract transfer2LiteralBuffer(): LiteralBuffer; } export class ClassType extends BaseType { @@ -43,8 +44,11 @@ export class ClassType extends BaseType { // pls extract class info here; } - extractFields() { + transfer2LiteralBuffer() { + let classLiteralBuf = new LiteralBuffer(); + // TODO add implementation; + return classLiteralBuf; } } @@ -66,4 +70,11 @@ export class FunctionType extends BaseType { // pls extract function info here } + transfer2LiteralBuffer() : LiteralBuffer { + let funcLiteralBuf = new LiteralBuffer(); + // TODO add implementation; + + return funcLiteralBuf; + } + } \ No newline at end of file diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index e823a72174..29f654f55f 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -183,6 +183,7 @@ import { CatchTable } from "./statement/tryStatement"; import { Variable } from "./variable"; +import { BaseType } from "./base/typeSystem"; export class PandaGen { private debugTag: string = "PandaGen"; @@ -201,8 +202,10 @@ export class PandaGen { private sourceFileDebugInfo: string = ""; private sourceCodeDebugInfo: string | undefined; private icSize: number = 0; + private typeRecord: Map = new Map(); private static literalArrayBuffer: Array = []; + private static typeArrayBuffer: Array = new Array(); constructor(internalName: string, parametersCount: number, scope: Scope | undefined = undefined) { this.internalName = internalName; @@ -257,6 +260,27 @@ export class PandaGen { this.icSize = total; } + getTypeRecord() { + return this.typeRecord; + } + + appendTypeRecord(vreg: VReg, type: number) { + if (this.typeRecord.has(vreg)) { + throw new Error("The vreg has been recorded, please check"); + } + + this.typeRecord.set(vreg, type); + } + + getTypeArrayBuffer() { + return PandaGen.typeArrayBuffer; + } + + appendTypeArrayBuffer(type: BaseType) { + let typeLiteralBuffer = type.transfer2LiteralBuffer(); + PandaGen.typeArrayBuffer.push(typeLiteralBuffer); + } + getFirstStmt() { return this.firstStmt; } diff --git a/ts2panda/src/pandasm.ts b/ts2panda/src/pandasm.ts index f4ca2651ae..732bfb83ea 100644 --- a/ts2panda/src/pandasm.ts +++ b/ts2panda/src/pandasm.ts @@ -72,6 +72,7 @@ export class Function { public variables: Array | undefined; public sourceFile: string; public sourceCode: string | undefined; + public typeInfo: Map; constructor( name: string, @@ -82,6 +83,7 @@ export class Function { variables: Array | undefined = undefined, sourceFile: string = "", sourceCode: string | undefined = undefined, + typeInfo: Map ) { this.name = name; this.signature = signature; @@ -93,6 +95,7 @@ export class Function { this.variables = variables; this.sourceFile = sourceFile; this.sourceCode = sourceCode; + this.typeInfo = typeInfo; } } diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 58e7765b79..086bbe5e26 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -170,6 +170,12 @@ export class Ts2Panda { let funcSignature = Ts2Panda.getFuncSignature(pg); let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); + let typeRecord = pg.getTypeRecord(); + let typeInfo = new Map(); + typeRecord.forEach((type, vreg) => { + let vregNum = vreg.num; + typeInfo.set(vregNum, type); + }); let variables, sourceCode; if (CmdOptions.isDebugMode()) { @@ -189,6 +195,7 @@ export class Ts2Panda { variables, sourceFile, sourceCode, + typeInfo ); let catchTables = generateCatchTables(pg.getCatchMap()); catchTables.forEach((catchTable) => { -- Gitee From 5c695c77474e93bad77f805b30b63839d73c28ef Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Fri, 24 Sep 2021 17:32:14 +0800 Subject: [PATCH 05/39] =?UTF-8?q?=E5=B0=86typescript=E7=9A=84=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8D=87=E7=BA=A7=E5=88=B04.1.3=20Signed-off-by:=20zg?= =?UTF-8?q?y-ian=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test262/config.py | 5 +- test262/run_sunspider.py | 11 +++- ts2panda/BUILD.gn | 10 ++- ts2panda/package-lock.json | 6 +- ts2panda/package.json | 2 +- ts2panda/src/compiler.ts | 16 ++++- ts2panda/src/debuginfo.ts | 5 +- ts2panda/src/jshelpers.d.ts | 7 ++- ts2panda/src/jshelpers.js | 11 +--- ts2panda/src/recorder.ts | 11 ++-- ts2panda/src/statement/classStatement.ts | 75 +++++++++++------------ ts2panda/src/statement/returnStatement.ts | 4 +- ts2panda/src/statement/tryStatement.ts | 20 +++--- ts2panda/src/syntaxChecker.ts | 26 +++++--- ts2panda/templates/diagnostic.ts.erb | 12 ++-- 15 files changed, 128 insertions(+), 93 deletions(-) diff --git a/test262/config.py b/test262/config.py index c521b973dd..20e8740229 100755 --- a/test262/config.py +++ b/test262/config.py @@ -32,6 +32,7 @@ CODE_ROOT = os.path.abspath(os.path.join(CUR_FILE_DIR, "../../..")) ARK_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/ark/ark" ICUI_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/global/i18n_standard" LLVM_DIR = f"{CODE_ROOT}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/" +ARK_JS_RUNTIME_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/ark/ark_js_runtime" # " mode_type": { # "1": "only default", @@ -45,8 +46,8 @@ TEST_ES2015_DIR = os.path.join(DATA_DIR, "test_es2015") TEST_CI_DIR = os.path.join(DATA_DIR, "test_CI") DEFAULT_ARK_FRONTEND_TOOL = os.path.join(ARK_DIR, "build", "src", "index.js") -DEFAULT_ARK_TOOL = os.path.join(ARK_DIR, "..", "ark_js_runtime", "ark_js_vm") -DEFAULT_LIBS_DIR = f"{ARK_DIR}:{ICUI_DIR}:{LLVM_DIR}" +DEFAULT_ARK_TOOL = os.path.join(ARK_JS_RUNTIME_DIR, "ark_js_vm") +DEFAULT_LIBS_DIR = f"{ARK_DIR}:{ICUI_DIR}:{LLVM_DIR}:{ARK_JS_RUNTIME_DIR}" DEFAULT_HOST_TYPE = "panda" DEFAULT_HOST_PATH = "python3" diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 97752ef074..7f9bce461f 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -31,14 +31,23 @@ from config import * def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--ark-tool', + default=DEFAULT_ARK_TOOL, + required=False, help="ark's binary tool") parser.add_argument('--ark-frontend-tool', + default=DEFAULT_ARK_FRONTEND_TOOL, + required=False, help="ark frontend conversion tool") parser.add_argument("--libs-dir", + default=DEFAULT_LIBS_DIR, + required=False, help="The path collection of dependent so has been divided by':'") parser.add_argument("--js-file", + required=True, help="js file") parser.add_argument('--ark-frontend', + default=DEFAULT_ARK_FRONTEND, + required=False, nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") arguments = parser.parse_args() @@ -155,7 +164,7 @@ class ArkProgram(): return retcode def execute(self): - + os.environ["LD_LIBRARY_PATH"] = self.libs_dir file_name_pre = os.path.splitext(self.js_file)[0] diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 212e144a54..f002aae0e7 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -25,9 +25,17 @@ ohos_copy("ts2abc_src") { module_install_name = "" } +action("npm_install") { + visibility = [ ":*" ] + script = "scripts/npm-install.sh" + args = [ rebase_path(node_path) ] + outputs = [ target_out_dir + "/$target_name/node_modules" ] + inputs = [ "${ts2abc_root}/package.json" ] +} + ohos_copy("node_modules") { sources = [ rebase_path("${node_modules}") ] - + deps = [ ":npm_install" ] outputs = [ target_out_dir + "/node_modules" ] module_install_name = "" } diff --git a/ts2panda/package-lock.json b/ts2panda/package-lock.json index 676cac87b2..8a580ee574 100755 --- a/ts2panda/package-lock.json +++ b/ts2panda/package-lock.json @@ -2302,9 +2302,9 @@ "dev": true }, "typescript": { - "version": "3.9.10", - "resolved": "http://mirrors.tools.huawei.com/npm/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/typescript/download/typescript-4.4.3.tgz?cache=0&sync_timestamp=1632381565165&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ftypescript%2Fdownload%2Ftypescript-4.4.3.tgz", + "integrity": "sha1-vcVAfKorEJ79T4L+EwZW+XeikyQ=", "dev": true }, "typical": { diff --git a/ts2panda/package.json b/ts2panda/package.json index 2fc7bed3c1..f37f0d41b6 100755 --- a/ts2panda/package.json +++ b/ts2panda/package.json @@ -33,7 +33,7 @@ "mocha": "^8.1.1", "sinon": "^9.0.3", "ts-sinon": "^1.2.1", - "typescript": "^3.9.7" + "typescript": "^4.1.3" }, "dependencies": { "@babel/core": "^7.12.10", diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index b87ad4cc6a..2b2e39a916 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -83,7 +83,9 @@ import { import { checkValidUseSuperBeforeSuper, compileClassDeclaration, - compileConstructor + compileConstructor, + compileDefaultConstructor, + isContainConstruct } from "./statement/classStatement"; import { compileForOfStatement } from "./statement/forOfStatement"; import { LabelTarget } from "./statement/labelTarget"; @@ -336,6 +338,14 @@ export class Compiler { let pandaGen = this.pandaGen; this.compileFunctionParameterDeclaration(decl); + if (ts.isConstructorDeclaration(decl)) { + let classNode = decl.parent; + if (jshelpers.getClassExtendsHeritageElement(classNode) && !isContainConstruct(classNode)) { + compileDefaultConstructor(this, decl); + return; + } + } + if (decl.kind == ts.SyntaxKind.FunctionExpression) { if (decl.name) { let funcName = jshelpers.getTextOfIdentifierOrLiteral(decl.name); @@ -554,7 +564,7 @@ export class Compiler { compileFinallyBeforeCFC(endTry: TryStatement | undefined, cfc: ControlFlowChange, continueTargetLabel: Label | undefined) {// compile finally before control flow change let startTry = TryStatement.getCurrentTryStatement(); let originTry = startTry; - for (; startTry != endTry; startTry = startTry ?.getOuterTryStatement()) { + for (; startTry != endTry; startTry = startTry?.getOuterTryStatement()) { if (startTry && startTry.trybuilder) { let inlineFinallyBegin = new Label(); @@ -616,7 +626,7 @@ export class Compiler { // try-catch-finally statements must have been transformed into // two nested try statements with only "catch" or "finally" each. if (stmt.catchClause && stmt.finallyBlock) { - transformTryCatchFinally(stmt, this.recorder); + stmt = transformTryCatchFinally(stmt, this.recorder); } let tryBuilder = new TryBuilder(this, this.pandaGen, stmt); diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index 527b8f0d50..6d05c0aa04 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -171,6 +171,9 @@ export class DebugInfo { let firstStmt = pandaGen.getFirstStmt(); if (firstStmt) { let file = jshelpers.getSourceFileOfNode(firstStmt); + if (!file) { + return; + } let loc = file.getLineAndCharacterOfPosition(firstStmt.getStart()); let wholeLineText = firstStmt.getText(); posInfo.setSourecLineNum(loc.line); @@ -199,7 +202,7 @@ export class DebugInfo { let wholeLineText = ""; if (DebugInfo.isNode(node)) { let tsNode = (node); - let file = jshelpers.getSourceFileOfNode(node); + let file = jshelpers.getSourceFileOfNode(tsNode); if (!file) { return; } diff --git a/ts2panda/src/jshelpers.d.ts b/ts2panda/src/jshelpers.d.ts index 5e4203d763..7138633f30 100644 --- a/ts2panda/src/jshelpers.d.ts +++ b/ts2panda/src/jshelpers.d.ts @@ -13,6 +13,8 @@ * limitations under the License. */ +import ts from "typescript"; + export function getSymbol(node: ts.Node): ts.Symbol; export function tsStringToString(str: ts.__String): string; export function getTextOfIdentifierOrLiteral(node: ts.Node): string; @@ -22,7 +24,6 @@ export function getFlowNode(stmt: ts.Statement): ts.Node; export function bindSourceFile(sourceFile: ts.SourceFile, options: ts.CompilerOptions); export function createDiagnosticForNode(node: ts.Node, message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.DiagnosticWithLocation; export function createCompilerDiagnostic(message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.Diagnostic; -export function createCompilerDiagnostic(message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.Diagnostic; export function createFileDiagnostic(file: ts.SourceFile, start: number, length: number, message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.DiagnosticWithLocation; export function isEffectiveStrictModeSourceFile(node: ts.SourceFile, compilerOptions: ts.CompilerOptions): boolean; export function getErrorSpanForNode(sourceFile: ts.SourceFile, node: ts.Node): ts.TextSpan; @@ -70,5 +71,5 @@ export function skipOuterExpressions(node: ts.Node, kinds?: ts.OuterExpressionKi export function isSuperCall(n: ts.Node); export function isThisProperty(node: ts.Node): boolean; export function isThisIdentifier(node: ts.Node | undefined): boolean; -export function getClassExtendsHeritageElement(node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration); -export function isSuperProperty(node: ts.Node); \ No newline at end of file +export function isSuperProperty(node: ts.Node); +export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined; \ No newline at end of file diff --git a/ts2panda/src/jshelpers.js b/ts2panda/src/jshelpers.js index a958271e22..e3c2960d8d 100755 --- a/ts2panda/src/jshelpers.js +++ b/ts2panda/src/jshelpers.js @@ -103,10 +103,6 @@ function getTextOfNode(node, includeTrivia) { return ts.getTextOfNode(node, includeTrivia); } -function getContainingClass(node) { - return ts.getContainingClass(node); -} - function nodePosToString(node) { return ts.nodePosToString(node); } @@ -247,8 +243,8 @@ function isSuperProperty(node) { return ts.isSuperProperty(node); } -function getClassExtendsHeritageElement(node) { - return ts.getClassExtendsHeritageElement(node); +function setParent(child, parent) { + return ts.setParent(child, parent); } module.exports = { @@ -274,7 +270,6 @@ module.exports = { getSourceFileOfNode: getSourceFileOfNode, isIterationStatement: isIterationStatement, getTextOfNode: getTextOfNode, - getContainingClass: getContainingClass, nodePosToString: nodePosToString, getContainingFunctionDeclaration: getContainingFunctionDeclaration, tokenToString: tokenToString, @@ -310,5 +305,5 @@ module.exports = { isThisIdentifier: isThisIdentifier, isThisProperty: isThisProperty, isSuperProperty: isSuperProperty, - getClassExtendsHeritageElement: getClassExtendsHeritageElement, + setParent: setParent, }; diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c..9f2b726696 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -217,7 +217,7 @@ export class Recorder { let tmp: Scope | undefined = nearestRefVariableScope.getNearestLexicalScope(); let needCreateLoopEnv: boolean = false; if (nearestDefLexicalScope instanceof LoopScope) { - while(tmp) { + while (tmp) { if (tmp == nearestDefLexicalScope) { needCreateLoopEnv = true; break; @@ -236,7 +236,7 @@ export class Recorder { if (name == "arguments") { let varialbeScope = scope.getNearestVariableScope(); - varialbeScope ?.setUseArgs(true); + varialbeScope?.setUseArgs(true); } } @@ -493,8 +493,11 @@ export class Recorder { // if variable share a same name with the parameter of its contained function, it should not be hoisted if (scope instanceof FunctionScope) { - let nearestFunc = jshelpers.getContainingFunction(node); - let functionParameters = this.getParametersOfFunction(nearestFunc); + let nearestFunc = jshelpers.getContainingFunctionDeclaration(node); + if (!nearestFunc) { + return; + } + let functionParameters = this.getParametersOfFunction(nearestFunc); if (functionParameters) { for (let i = 0; i < functionParameters.length; i++) { if (functionParameters[i].name == declName) { diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 1163c9e0b8..a694437b44 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -132,41 +132,23 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe export function AddCtor2Class(recorder: Recorder, classNode: ts.ClassLikeDeclaration, scope: Scope) { let ctorNode; - let hasHeritage = classNode.heritageClauses && classNode.heritageClauses.length; - let statement: ts.Statement | undefined; - let superCallNode = ts.createSuper(); - if (hasHeritage) { - let parameter = ts.createParameter(undefined, undefined, ts.createToken(ts.SyntaxKind.DotDotDotToken), "args"); - ctorNode = ts.createConstructor(undefined, undefined, [parameter], undefined); - let callNode = ts.createCall( - superCallNode, - undefined, - [ts.createSpread(ts.createIdentifier("args"))] - ); - superCallNode.parent = callNode; - superCallNode.pos = classNode.pos; - superCallNode.end = classNode.pos; - statement = ts.createExpressionStatement(callNode); - callNode.parent = statement; - callNode.pos = classNode.pos; - callNode.end = classNode.pos; + if (jshelpers.getClassExtendsHeritageElement(classNode)) { + let parameter = ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), "args"); + ctorNode = ts.factory.createConstructorDeclaration(undefined, undefined, [parameter], undefined); } else { - ctorNode = ts.createConstructor(undefined, undefined, [], undefined); + ctorNode = ts.factory.createConstructorDeclaration(undefined, undefined, [], undefined); } - if (statement) { - ctorNode.body = ts.createBlock([statement]); - statement.parent = ctorNode; - statement.pos = classNode.pos; - statement.end = classNode.pos; - } else { - ctorNode.body = ts.createBlock([]); - } + ctorNode = jshelpers.setParent(ctorNode, classNode)!; + ctorNode = ts.setTextRange(ctorNode, classNode); + + let body = ts.factory.createBlock([]); + body = jshelpers.setParent(body, ctorNode)!; + body = ts.setTextRange(body, classNode)!; - ctorNode.parent = classNode; - ctorNode.pos = classNode.pos; - ctorNode.end = classNode.pos; - ctorNode.body!.parent = ctorNode; + ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, undefined, undefined, ctorNode.parameters, body); + ctorNode = jshelpers.setParent(ctorNode, classNode)!; + ctorNode = ts.setTextRange(ctorNode, classNode); let parentScope = recorder.getScopeOfNode(classNode); recorder.compilerDriver.getFuncId(classNode); @@ -183,6 +165,17 @@ export function AddCtor2Class(recorder: Recorder, classNode: ts.ClassLikeDeclara recorder.recordFunctionParameters(ctorNode); } +export function compileDefaultConstructor(compiler: Compiler, ctrNode: ts.ConstructorDeclaration) { + let callNode = ts.factory.createCallExpression(ts.factory.createSuper(), undefined, + [ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))]); + + callNode = jshelpers.setParent(callNode, ctrNode)!; + callNode = ts.setTextRange(callNode, ctrNode)! + + compileSuperCall(compiler, callNode, [], true); + compileConstructor(compiler, ctrNode, false); +} + function compileUnCompiledProperty(compiler: Compiler, properties: Property[], classReg: VReg) { let pandaGen = compiler.getPandaGen(); for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) { @@ -248,7 +241,7 @@ function createClassLiteralBuf(compiler: Compiler, classBuffer: LiteralBuffer, export function compileConstructor(compiler: Compiler, node: ts.ConstructorDeclaration, unreachableFlag: boolean) { let pandaGen = compiler.getPandaGen(); - let members = node.parent.members; + let members = node.parent!.members; for (let index = 0; index < members.length; index++) { let decl = members[index]; @@ -325,19 +318,23 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { let recorder = compiler.getRecorder(); let pandaGen = compiler.getPandaGen(); - let nearestFunc = jshelpers.getContainingFunction(node); + let nearestFunc = jshelpers.getContainingFunctionDeclaration(node); + if (!nearestFunc) { + return; + } + let nearestFuncScope = recorder.getScopeOfNode(nearestFunc); if (ts.isConstructorDeclaration(nearestFunc)) { let funcObj = nearestFuncScope.findLocal("4funcObj"); pandaGen.loadAccumulator(node, pandaGen.getVregForVariable(funcObj)); } else { - let outerFunc = jshelpers.getContainingFunction(nearestFunc); - let outerFuncScope = recorder.getScopeOfNode(outerFunc); + let outerFunc = jshelpers.getContainingFunctionDeclaration(nearestFunc); + let outerFuncScope = recorder.getScopeOfNode(outerFunc!); outerFuncScope.pendingCreateEnv(); let level = 1; - while (!ts.isConstructorDeclaration(outerFunc)) { - outerFunc = jshelpers.getContainingFunction(outerFunc); + while (!ts.isConstructorDeclaration(outerFunc!)) { + outerFunc = jshelpers.getContainingFunctionDeclaration(outerFunc!); outerFuncScope.pendingCreateEnv(); level++; } @@ -424,7 +421,7 @@ export function getClassNameForConstructor(classNode: ts.ClassLikeDeclaration) { let className = ""; if (!isAnonymousClass(classNode)) { - className = jshelpers.getTextOfIdentifierOrLiteral(classNode.name); + className = jshelpers.getTextOfIdentifierOrLiteral(classNode.name!); } else { let outerNode = findOuterNodeOfParenthesis(classNode); @@ -646,7 +643,7 @@ function scalarArrayEquals(node1: ts.Node | undefined, node2: ts.Node | undefine let val1Modifs = node1.modifiers; let val2Modifs = node2.modifiers; if (val1Modifs && val2Modifs) { - return val1Modifs.length == val2Modifs.length && val1Modifs.every(function(v, i) { return v === val2Modifs![i] });; + return val1Modifs.length == val2Modifs.length && val1Modifs.every(function (v, i) { return v === val2Modifs![i] });; } if (!val1Modifs && !val2Modifs) { diff --git a/ts2panda/src/statement/returnStatement.ts b/ts2panda/src/statement/returnStatement.ts index 221db0bb2e..90510ba9b3 100644 --- a/ts2panda/src/statement/returnStatement.ts +++ b/ts2panda/src/statement/returnStatement.ts @@ -134,8 +134,8 @@ function compileNormalReturn(stmt: ts.ReturnStatement, returnValue: VReg, compil } function isReturnInDerivedCtor(stmt: ts.ReturnStatement) { - let funcNode = jshelpers.getContainingFunction(stmt); - if (!ts.isConstructorDeclaration(funcNode)) { + let funcNode = jshelpers.getContainingFunctionDeclaration(stmt); + if (!funcNode || !ts.isConstructorDeclaration(funcNode)) { return false; } diff --git a/ts2panda/src/statement/tryStatement.ts b/ts2panda/src/statement/tryStatement.ts index 6107c01453..3f337a912a 100644 --- a/ts2panda/src/statement/tryStatement.ts +++ b/ts2panda/src/statement/tryStatement.ts @@ -28,9 +28,10 @@ import { import { IteratorType, IteratorRecord } from "./forOfStatement"; import * as astutils from "../astutils"; import { VarDeclarationKind } from "../variable"; +import jshelpers from "../jshelpers"; // adjust the try...catch...finally into nested try(try...catch) finally -export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Recorder) { +export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Recorder): ts.TryStatement { // after create new try block node, mapped with new scope, and adjust parent node let tryStmtScope = recorder.getScopeOfNode(tryStmt); let newTryBlockScope = new LocalScope(tryStmtScope); @@ -38,18 +39,17 @@ export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Rec (recorder.getScopeOfNode(tryStmt.tryBlock)).setParent(newTryStmtScope); (recorder.getScopeOfNode(tryStmt.catchClause!)).setParent(newTryStmtScope); - const newTryStmt = ts.createTry(tryStmt.tryBlock, tryStmt.catchClause, undefined); + // const newTryStmt = ts.createTry(tryStmt.tryBlock, tryStmt.catchClause, undefined); + const newTryStmt = ts.factory.createTryStatement(tryStmt.tryBlock, tryStmt.catchClause, undefined); recorder.setScopeMap(newTryStmt, newTryStmtScope); const newTryBlock = [newTryStmt]; - newTryBlock[0].pos = tryStmt.tryBlock.pos; - newTryBlock[0].end = tryStmt.tryBlock.end; - tryStmt.tryBlock = ts.updateBlock(tryStmt.tryBlock, newTryBlock); - newTryBlock[0].parent = tryStmt.tryBlock; - + newTryBlock[0] = jshelpers.setParent(newTryBlock[0], tryStmt)!; + newTryBlock[0] = ts.setTextRange(newTryBlock[0], tryStmt.tryBlock)!; + let tryBlock = ts.factory.updateBlock(tryStmt.tryBlock, newTryBlock); + tryStmt = ts.factory.updateTryStatement(tryStmt, tryBlock, undefined, tryStmt.finallyBlock); recorder.setScopeMap(tryStmt.tryBlock, newTryBlockScope); - tryStmt.catchClause = undefined; - tryStmt = ts.updateTry(tryStmt, tryStmt.tryBlock, undefined, tryStmt.finallyBlock); + return tryStmt; } export class LabelPair { @@ -359,7 +359,7 @@ function compileCatchClauseVariableDeclaration(compiler: Compiler, param: ts.Var } export function updateCatchTables(inlinedTry: TryStatement | undefined, targetTry: TryStatement, inlinedLabelPair: LabelPair) { - for (; inlinedTry != targetTry; inlinedTry = inlinedTry ?.getOuterTryStatement()) { + for (; inlinedTry != targetTry; inlinedTry = inlinedTry?.getOuterTryStatement()) { inlinedTry!.getCatchTable().splitLabelPair(inlinedLabelPair); } targetTry.getCatchTable().splitLabelPair(inlinedLabelPair); diff --git a/ts2panda/src/syntaxChecker.ts b/ts2panda/src/syntaxChecker.ts index a9fe751dda..185e3a2df3 100644 --- a/ts2panda/src/syntaxChecker.ts +++ b/ts2panda/src/syntaxChecker.ts @@ -21,7 +21,7 @@ import { } from "./diagnostic"; import { hasExportKeywordModifier } from "./base/util"; import { findInnerExprOfParenthesis } from "./expression/parenthesizedExpression"; -import jshelpers, { getContainingFunction, getSourceFileOfNode } from "./jshelpers"; +import jshelpers, { getContainingFunction, getContainingFunctionDeclaration, getSourceFileOfNode } from "./jshelpers"; import { LOGE } from "./log"; import { Recorder } from "./recorder"; import { @@ -73,7 +73,7 @@ export function checkDuplicateDeclaration(recorder: Recorder) { } // implement catchParameter-related duplicate-entry check - if ((node.kind == ts.SyntaxKind.Block) && (node.parent.kind == ts.SyntaxKind.CatchClause)) { + if ((node.kind == ts.SyntaxKind.Block) && (node.parent != undefined && node.parent.kind == ts.SyntaxKind.CatchClause)) { let catchScope = scopeMap.get(node.parent); checkDuplicateInCatch(scope, catchScope); } @@ -355,12 +355,11 @@ function checkMetaProperty(node: ts.MetaProperty) { if (!getContainingFunction(node)) { throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); } else { - let func = getContainingFunction(node); - while (getContainingFunction(func)) { - func = getContainingFunction(func); + let func = getContainingFunctionDeclaration(node); + while (getContainingFunctionDeclaration(func!)) { + func = getContainingFunctionDeclaration(func!); } - - if (ts.isArrowFunction(func)) { + if (func && ts.isArrowFunction(func)) { throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); } } @@ -1051,7 +1050,7 @@ function getPropertieDeclaration(node: ts.Node, name: ts.Node) { function checkDisallowedTrailingComma(list: ts.NodeArray | undefined) { if (list && list.hasTrailingComma) { - let file = jshelpers.getSourceFileOfNode(list); + let file = jshelpers.getSourceFileOfNode(list[0]); throw new DiagnosticError(list[0], DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); } } @@ -1059,10 +1058,10 @@ function checkDisallowedTrailingComma(list: ts.NodeArray | undefined) { function checkParameters(parameters: ts.NodeArray) { let count = parameters.length; let optionalParameter = false; - let file = jshelpers.getSourceFileOfNode(parameters); for (let i = 0; i < count; i++) { let parameter = parameters[i]; + let file = jshelpers.getSourceFileOfNode(parameter); if (parameter.dotDotDotToken) { if (i != count - 1) { throw new DiagnosticError(parameter.dotDotDotToken, DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list, file); @@ -1205,6 +1204,12 @@ function checkRegularExpression(regexp: ts.RegularExpressionLiteral) { new regexpParse().parseLiteral(regexpText); } +function checkThrowStatement(node: ts.ThrowStatement) { + if (ts.isIdentifier(node.expression) && (node.expression).text === '') { + throw new DiagnosticError(node, DiagnosticCode.Line_break_not_permitted_here, jshelpers.getSourceFileOfNode(node)); + } +} + function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node) { switch (node.kind) { case ts.SyntaxKind.BreakStatement: @@ -1270,6 +1275,9 @@ function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node) { case ts.SyntaxKind.RegularExpressionLiteral: checkRegularExpression(node); break; + case ts.SyntaxKind.ThrowStatement: + checkThrowStatement(node); + break; default: break; } diff --git a/ts2panda/templates/diagnostic.ts.erb b/ts2panda/templates/diagnostic.ts.erb index a6df2d5730..795fda099a 100755 --- a/ts2panda/templates/diagnostic.ts.erb +++ b/ts2panda/templates/diagnostic.ts.erb @@ -17,10 +17,10 @@ import { LOGE } from "./log" export class DiagnosticError { irnode:ts.Node | undefined; code:number; - file: ts.Node | undefined; + file: ts.SourceFile | undefined; args: (string | number | undefined)[]; - constructor(irnode:ts.Node | undefined, code:number,file?:ts.Node | undefined ,args?:(string | number | undefined)[]) { + constructor(irnode:ts.Node | undefined, code:number, file?:ts.SourceFile | undefined, args?:(string | number | undefined)[]) { this.code = code this.irnode = irnode this.file = file ? file : undefined @@ -40,13 +40,13 @@ export function printDiagnostic(diagnostic: ts.Diagnostic) { } -export function createDiagnosticOnFirstToken(file:ts.Node | undefined,node: ts.Node ,message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createDiagnosticOnFirstToken(file:ts.SourceFile, node: ts.Node ,message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { let span = jshelpers.getSpanOfTokenAtPosition(file, node.pos); let diagnostic = jshelpers.createFileDiagnostic(file,span.start,span.length,message,...args); return diagnostic; } -export function createFileDiagnostic(file:ts.Node|undefined,node: ts.Node , message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createFileDiagnostic(file:ts.SourceFile, node: ts.Node, message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { let diagnostic; let span = jshelpers.getErrorSpanForNode(file, node); @@ -68,7 +68,7 @@ export function createFileDiagnostic(file:ts.Node|undefined,node: ts.Node , mess return diagnostic; } -export function createDiagnostic(file:ts.Node|undefined, location: ts.Node | undefined, message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createDiagnostic(file:ts.SourceFile | undefined, location: ts.Node | undefined, message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { var diagnostic; if (!location) { @@ -76,7 +76,7 @@ export function createDiagnostic(file:ts.Node|undefined, location: ts.Node | und } if (file) { - diagnostic = createFileDiagnostic(file,location,message,...args); + diagnostic = createFileDiagnostic(file, location, message, ...args); } else { diagnostic = jshelpers.createDiagnosticForNode(location, message, ...args) } -- Gitee From 95da08da4614d1e7d181edcae9b2f26f7cf9dec9 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Sun, 26 Sep 2021 12:13:50 +0800 Subject: [PATCH 06/39] fix incorrect imports in variable/irnods Signed-off-by: zhuoli Change-Id: If742d2e0a771c73281603bbad92ee73b58046543 --- ts2panda/src/base/typeSystem.ts | 40 ++++++++++++++++++++++++++----- ts2panda/src/variable.ts | 4 ++-- ts2panda/templates/irnodes.ts.erb | 2 ++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index f163115a66..7ccba1a9dd 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -36,12 +36,40 @@ export class ClassType extends BaseType { constructor(classNode: ts.ClassDeclaration) { super(); + this.fillInModifiers(classNode); + this.fillInHeritages(classNode); + this.fillInFields(classNode); + this.fillInMethods(classNode); + } - if (classNode.AbstractKeyword) { - this.modifier = 1; + fillInModifiers(node: ts.ClassDeclaration) { + if (node.modifiers) { + for (let modifier of node.modifiers) { + switch (modifier.kind) { + case ts.SyntaxKind.AbstractKeyword: { + this.modifier = 1; + break; + } + case ts.SyntaxKind.ExportKeyword: { + break; + } + } + } } + } + + fillInHeritages(node: ts.ClassDeclaration) { + if (node.heritageClauses) { + + } + } + + fillInFields(node: ts.ClassDeclaration) { + + } + + fillInMethods(node: ts.ClassDeclaration) { - // pls extract class info here; } transfer2LiteralBuffer() { @@ -63,9 +91,9 @@ export class FunctionType extends BaseType { constructor(funcNode: ts.FunctionLikeDeclaration) { super(); - if (funcNode.AbstractKeyword) { - this.modifier = 1; - } + // if (funcNode.AbstractKeyword) { + // this.modifier = 1; + // } // pls extract function info here } diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 60226e2b72..ccf444cf5d 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -19,7 +19,7 @@ import { LoopScope, VariableScope } from "./scope"; -import { PremitiveType } from "./typeinfo" +import { PremitiveType } from "./base/typeSystem" export enum VarDeclarationKind { NONE, @@ -49,7 +49,7 @@ export abstract class Variable { bindVreg(vreg: VReg) { this.vreg = vreg; - this.vreg.setType(this.typeIndex); + this.vreg.setTypeIndex(this.typeIndex); } hasAlreadyBinded(): boolean { diff --git a/ts2panda/templates/irnodes.ts.erb b/ts2panda/templates/irnodes.ts.erb index eb8bb5f89e..3d06397785 100755 --- a/ts2panda/templates/irnodes.ts.erb +++ b/ts2panda/templates/irnodes.ts.erb @@ -25,6 +25,7 @@ import { NodeKind } from "./debuginfo"; import { LOGE } from "./log" +import { PremitiveType } from "./base/typeSystem" export enum IRNodeKind { VREG, @@ -202,6 +203,7 @@ export class VReg { constructor() { this.id = VReg.global_id++; + this.typeIndex = PremitiveType.UNDEFINED; // for debug purposes this.setStackTrace(null); -- Gitee From 2694c33af62800f91c484de104418d58c869a396 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Sun, 26 Sep 2021 10:26:53 +0800 Subject: [PATCH 07/39] init typechecker Signed-off-by: zhangrengao Change-Id: I5a80156462978a246943ac95966386322f2d2bdc --- ts2panda/src/index.ts | 5 ++++- ts2panda/src/recorder.ts | 5 +++++ ts2panda/src/typeChecker.ts | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 ts2panda/src/typeChecker.ts diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index f778f0a75e..fb3c296e57 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -24,16 +24,19 @@ import { ICPass } from "./pass/ICPass"; import { RegAlloc } from "./regAllocator"; import { setGlobalStrict } from "./strictMode"; import jshelpers = require("./jshelpers"); +import { TypeChecker } from "./typeChecker"; function main(fileNames: string[], options: ts.CompilerOptions) { let program = ts.createProgram(fileNames, options); + let typeChecker = TypeChecker.getInstance(); + typeChecker.setTypeChecker(program.getTypeChecker()); let emitResult = program.emit( undefined, undefined, undefined, undefined, { - before: [ + after: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { let outputBinName = CmdOptions.getOutputBinName(); diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index eb1761116c..c62e0ceb0b 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -49,6 +49,7 @@ import { import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; +import { TypeChecker } from "./typeChecker"; export class Recorder { node: ts.Node; @@ -164,6 +165,10 @@ export class Recorder { this.recordInfo(childNode, scope); break; } + case ts.SyntaxKind.VariableStatement: { + TypeChecker.getInstance().formatNodeType(childNode); + break; + } default: this.recordInfo(childNode, scope); } diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts new file mode 100644 index 0000000000..3873e5fd08 --- /dev/null +++ b/ts2panda/src/typeChecker.ts @@ -0,0 +1,37 @@ +import ts from "typescript"; + +export class TypeChecker { + private static instance: TypeChecker; + private compiledTypeChecker: any = null; + private constructor() {} + + public static getInstance(): TypeChecker { + if (!TypeChecker.instance) { + TypeChecker.instance = new TypeChecker(); + } + return TypeChecker.instance; + } + + public setTypeChecker(typeChecker: ts.TypeChecker) { + this.compiledTypeChecker = typeChecker; + } + + public getTypeChecker() : ts.TypeChecker { + return this.compiledTypeChecker; + } + + public formatNodeType(node: ts.Node) { + if (this.compiledTypeChecker === null) { + return ; + } + if (node.kind === ts.SyntaxKind.VariableStatement) { + const variableStatementNode = node; + const decList = variableStatementNode.declarationList; + decList.declarations.forEach(declaration => { + const nameNode = declaration.name; + let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); + console.log(type.getSymbol()?.valueDeclaration); + }) + } + } +} -- Gitee From ad43de5606d8c7cb09ba002163a47c5397db92fd Mon Sep 17 00:00:00 2001 From: ctw Date: Sun, 26 Sep 2021 20:53:41 +0800 Subject: [PATCH 08/39] Implement transferType2LiteralBuffer Signed-off-by: ctw Change-Id: Ia5360bb3e4af666a5725068354859e3fd141d610 --- ts2panda/src/base/literal.ts | 2 ++ ts2panda/src/base/typeSystem.ts | 61 ++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 12 deletions(-) mode change 100755 => 100644 ts2panda/src/base/literal.ts diff --git a/ts2panda/src/base/literal.ts b/ts2panda/src/base/literal.ts old mode 100755 new mode 100644 index e246cdc496..b502f5d39d --- a/ts2panda/src/base/literal.ts +++ b/ts2panda/src/base/literal.ts @@ -22,6 +22,8 @@ export enum LiteralTag { GENERATOR = 7, ACCESSOR = 8, METHODAFFILIATE = 9, + MODIFIER = 10, + ACCESSFLAG = 11, NULLVALUE = 255 } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 7ccba1a9dd..26906bc1e3 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -14,7 +14,11 @@ */ import * as ts from "typescript"; -import { Literal, LiteralBuffer } from "./literal"; +import { + Literal, + LiteralBuffer, + LiteralTag +} from "./literal"; export enum PremitiveType { UNDEFINED, @@ -32,7 +36,7 @@ export class ClassType extends BaseType { modifier: number = 0; // 0 -> unabstract, 1 -> abstract; heritages: Array = new Array(); fields : Map> = new Map>(); // Array: [type][static][public/private] - Methods: Array = new Array(); + methods: Array = new Array(); constructor(classNode: ts.ClassDeclaration) { super(); @@ -73,17 +77,38 @@ export class ClassType extends BaseType { } transfer2LiteralBuffer() { - let classLiteralBuf = new LiteralBuffer(); - // TODO add implementation; - - return classLiteralBuf; + let classTypeBuf = new LiteralBuffer(); + let classTypeLiterals: Array = new Array(); + + classTypeLiterals.push(new Literal(LiteralTag.MODIFIER, this.modifier)); // modifier is added at the front + + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded + this.heritages.forEach(heritage => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); + }); + + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.fields.size)); // num of fields are recorded + this.fields.forEach((typeInfo, name) => { + classTypeLiterals.push(new Literal(LiteralTag.STRING, name)); + classTypeLiterals.push(new Literal(LiteralTag.MODIFIER, typeInfo[0])); + classTypeLiterals.push(new Literal(LiteralTag.ACCESSFLAG, typeInfo[1])); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); + }); + + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded + this.fields.forEach(method => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); + }); + + classTypeBuf.addLiterals(...classTypeLiterals); + return classTypeBuf; } } export class FunctionType extends BaseType { - modifierPublic: number = 0; - modifierStatic: number = 0; // 0 -> normal function or method, 1 -> static member of class + accessFlag: number = 0; // 0 -> private, 1 -> public + modifier: number = 0; // 0 -> unstatic, 1 -> static name: string = ''; parameters: Map = new Map(); returnType: number = 0; @@ -99,10 +124,22 @@ export class FunctionType extends BaseType { } transfer2LiteralBuffer() : LiteralBuffer { - let funcLiteralBuf = new LiteralBuffer(); - // TODO add implementation; - - return funcLiteralBuf; + let funcTypeBuf = new LiteralBuffer(); + let funcTypeLiterals: Array = new Array(); + funcTypeLiterals.push(new Literal(LiteralTag.ACCESSFLAG, this.accessFlag)); + funcTypeLiterals.push(new Literal(LiteralTag.MODIFIER, this.modifier)); + funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); + + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.size)); + this.parameters.forEach((type, paramName) => { + funcTypeLiterals.push(new Literal(LiteralTag.STRING, paramName)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); + }); + + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); + + funcTypeBuf.addLiterals(...funcTypeLiterals); + return funcTypeBuf; } } \ No newline at end of file -- Gitee From 4eedac0cb96583f45bcb652672004939171e2ea1 Mon Sep 17 00:00:00 2001 From: ctw Date: Mon, 27 Sep 2021 16:36:54 +0800 Subject: [PATCH 09/39] Write vreg-type info to function annotation Signed-off-by: ctw Change-Id: I5a71fdb1a5e3720d24e3ea531652c5c9e8b4aa43 --- ts2panda/src/base/typeSystem.ts | 10 ++++++++ ts2panda/src/pandagen.ts | 3 +-- ts2panda/src/pandasm.ts | 5 ++-- ts2panda/src/ts2panda.ts | 8 ++++--- ts2panda/ts2abc/ts2abc.cpp | 41 +++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 26906bc1e3..dc82831fbc 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -142,4 +142,14 @@ export class FunctionType extends BaseType { return funcTypeBuf; } +} + +export class TypeOfVreg { + private vregNum: number; + private typeIndex: number; + + constructor(vregNum: number, typeIndex: number) { + this.vregNum = vregNum; + this.typeIndex = typeIndex; + } } \ No newline at end of file diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 29f654f55f..6f2fb9a8b0 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -277,8 +277,7 @@ export class PandaGen { } appendTypeArrayBuffer(type: BaseType) { - let typeLiteralBuffer = type.transfer2LiteralBuffer(); - PandaGen.typeArrayBuffer.push(typeLiteralBuffer); + PandaGen.typeArrayBuffer.push(type.transfer2LiteralBuffer()); } getFirstStmt() { diff --git a/ts2panda/src/pandasm.ts b/ts2panda/src/pandasm.ts index 732bfb83ea..154d51ad5d 100644 --- a/ts2panda/src/pandasm.ts +++ b/ts2panda/src/pandasm.ts @@ -15,6 +15,7 @@ import { DebugPosInfo, VariableDebugInfo } from "./debuginfo"; import { LiteralBuffer } from "./base/literal"; +import { TypeOfVreg } from "./base/typeSystem"; export class Metadata { public attribute: string; @@ -72,7 +73,7 @@ export class Function { public variables: Array | undefined; public sourceFile: string; public sourceCode: string | undefined; - public typeInfo: Map; + public typeInfo: Array; constructor( name: string, @@ -83,7 +84,7 @@ export class Function { variables: Array | undefined = undefined, sourceFile: string = "", sourceCode: string | undefined = undefined, - typeInfo: Map + typeInfo: Array ) { this.name = name; this.signature = signature; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 086bbe5e26..e0d8c6fa32 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -27,6 +27,7 @@ import { PandaGen } from "./pandagen"; import { CatchTable, Function, Ins, Signature } from "./pandasm"; import { generateCatchTables } from "./statement/tryStatement"; import { escapeUnicode, isRangeInst, getRangeStartVregPos } from "./base/util"; +import { TypeOfVreg } from "./base/typeSystem"; const dollarSign: RegExp = /\$/g; @@ -171,10 +172,11 @@ export class Ts2Panda { let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); let typeRecord = pg.getTypeRecord(); - let typeInfo = new Map(); + + let typeInfo = new Array(); typeRecord.forEach((type, vreg) => { - let vregNum = vreg.num; - typeInfo.set(vregNum, type); + let typeOfVreg = new TypeOfVreg(vreg.num, type); + typeInfo.push(typeOfVreg); }); let variables, sourceCode; diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 0c8b4fd68b..f665032c39 100755 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -600,6 +600,36 @@ static void ParseFunctionCatchTables(const Json::Value &function, panda::pandasm } } +static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc) +{ + if (function.isMember("typeInfo") && function["typeInfo"].isArray()) { + auto typeInfo = function["typeInfo"]; + panda::pandasm::AnnotationData funcAnnotation("_ESTypeAnnotation"); + for (Json::ArrayIndex i = 0; i < typeInfo.size(); i++) { + auto type = typeInfo[i]; + if (!type.isObject()) { + continue; + } + + // TODO add type-vreg info to function annotation + uint32_t vregNum = 0; + if (type.isMember("vregNum") && type["vregNum"].isInt()) { + vregNum = type["vregNum"].asUInt(); + } + + uint32_t typeIndex = 0; + if (type.isMember("typeIndex") && type["typeIndex"].isInt()) { + typeIndex = type["typeIndex"].asUInt(); + } + + panda::pandasm::AnnotationElement typeOfVregElement(std::to_string(vregNum), std::make_unique(panda::pandasm::ScalarValue::Create(typeIndex))); + funcAnnotation.AddElement(std::move(typeOfVregElement)); + } + + const_cast&>(pandaFunc.metadata->GetAnnotations()).push_back(std::move(funcAnnotation)); + } +} + static panda::pandasm::Function ParseFunction(const Json::Value &function) { auto pandaFunc = GetFunctionDefintion(function); @@ -613,10 +643,20 @@ static panda::pandasm::Function ParseFunction(const Json::Value &function) ParseFunctionLabels(function, pandaFunc); // parsing catch blocks ParseFunctionCatchTables(function, pandaFunc); + // parsing type info + ParseFunctionTypeInfo(function, pandaFunc); return pandaFunc; } +static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog) +{ + auto tsTypeAnnotationRecord = panda::pandasm::Record("_ESTypeAnnotation", LANG_EXT); + tsTypeAnnotationRecord.metadata->SetAttribute("external"); + tsTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION); + prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord)); +} + static void GenrateESModuleModeRecord(panda::pandasm::Program &prog, bool moduleMode) { auto ecmaModuleModeRecord = panda::pandasm::Record("_ESModuleMode", LANG_EXT); @@ -711,6 +751,7 @@ static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, co static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program &prog) { + GenerateESTypeAnnotationRecord(prog); ParseModuleMode(rootValue, prog); ParseLogEnable(rootValue); ParseDebugMode(rootValue); -- Gitee From 9424961090ac6abd78933c465bb997c57459348c Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Sun, 26 Sep 2021 11:44:29 +0800 Subject: [PATCH 10/39] =?UTF-8?q?=E6=B7=BB=E5=8A=A0npm=20install=20?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgy-ian --- ts2panda/scripts/npm-install.sh | 40 ++++++++++++++++++++++++++ ts2panda/src/statement/tryStatement.ts | 1 - 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100755 ts2panda/scripts/npm-install.sh diff --git a/ts2panda/scripts/npm-install.sh b/ts2panda/scripts/npm-install.sh new file mode 100755 index 0000000000..f806d55df0 --- /dev/null +++ b/ts2panda/scripts/npm-install.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright (c) 2021 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. +set -e + +script_path=$(cd $(dirname $0);pwd) +ts2panda_dir=$(dirname ${script_path}) +code_dir=${ts2panda_dir}/../../.. + +nodejs_dir=$1 + +cd ${ts2panda_dir} +export PATH=${nodejs_dir}:$PATH +npm config set registry http://registry.npm.taobao.org +if [ "X${SKIP_SSL}" == "XYES" ];then + npm config set strict-ssl false +fi +npm cache clean -f +npm install + +cd ${code_dir} +if [ -d "${code_dir}/prebuilts/build-tools/common/ts2abc" ]; then + echo -e "\n" + echo "${code_dir}/prebuilts/build-tools/common/ts2abc already exist, it will be replaced" + /bin/rm -rf ${code_dir}/prebuilts/build-tools/common/ts2abc + echo -e "\n" +fi + +mkdir -p ${code_dir}/prebuilts/build-tools/common/ts2abc +/bin/cp -rf ${code_dir}/ark/ts2abc/ts2panda/node_modules ${code_dir}/prebuilts/build-tools/common/ts2abc/ \ No newline at end of file diff --git a/ts2panda/src/statement/tryStatement.ts b/ts2panda/src/statement/tryStatement.ts index 3f337a912a..d720e5420d 100644 --- a/ts2panda/src/statement/tryStatement.ts +++ b/ts2panda/src/statement/tryStatement.ts @@ -39,7 +39,6 @@ export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Rec (recorder.getScopeOfNode(tryStmt.tryBlock)).setParent(newTryStmtScope); (recorder.getScopeOfNode(tryStmt.catchClause!)).setParent(newTryStmtScope); - // const newTryStmt = ts.createTry(tryStmt.tryBlock, tryStmt.catchClause, undefined); const newTryStmt = ts.factory.createTryStatement(tryStmt.tryBlock, tryStmt.catchClause, undefined); recorder.setScopeMap(newTryStmt, newTryStmtScope); -- Gitee From d5a0cb67158e4b1ad374e508aacf01b72d91a344 Mon Sep 17 00:00:00 2001 From: ctw Date: Tue, 28 Sep 2021 16:49:31 +0800 Subject: [PATCH 11/39] using literalbuffer to store types Signed-off-by: ctw Change-Id: I7fba8969be6feea44f6bda1886f12183bec0e6a6 --- ts2panda/src/base/typeSystem.ts | 33 +++++++++++++++++++++++++-------- ts2panda/src/pandagen.ts | 13 +++++-------- ts2panda/src/ts2panda.ts | 3 ++- ts2panda/ts2abc/ts2abc.cpp | 10 ++++++++-- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index dc82831fbc..d3b8c48c36 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -28,6 +28,12 @@ export enum PremitiveType { _LENGTH } +export enum L2Type { + CLASS, + FUNCTION, + OBJECT // object literal +} + export abstract class BaseType { abstract transfer2LiteralBuffer(): LiteralBuffer; } @@ -110,16 +116,12 @@ export class FunctionType extends BaseType { accessFlag: number = 0; // 0 -> private, 1 -> public modifier: number = 0; // 0 -> unstatic, 1 -> static name: string = ''; - parameters: Map = new Map(); + parameters: Array = new Array(); returnType: number = 0; constructor(funcNode: ts.FunctionLikeDeclaration) { super(); - // if (funcNode.AbstractKeyword) { - // this.modifier = 1; - // } - // pls extract function info here } @@ -130,9 +132,8 @@ export class FunctionType extends BaseType { funcTypeLiterals.push(new Literal(LiteralTag.MODIFIER, this.modifier)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.size)); - this.parameters.forEach((type, paramName) => { - funcTypeLiterals.push(new Literal(LiteralTag.STRING, paramName)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); + this.parameters.forEach((type) => { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); }); @@ -141,7 +142,23 @@ export class FunctionType extends BaseType { funcTypeBuf.addLiterals(...funcTypeLiterals); return funcTypeBuf; } +} + +export class ObjectLiteralType extends BaseType { + private properties: Map = new Map(); + private methods: Array = new Array(); + + constructor(obj: ts.ObjectLiteralExpression) { + super(); + + // TODO extract object info here + } + transfer2LiteralBuffer() : LiteralBuffer { + let objTypeBuf = new LiteralBuffer(); + + return objTypeBuf; + } } export class TypeOfVreg { diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 6f2fb9a8b0..cd0f259fbd 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -204,8 +204,7 @@ export class PandaGen { private icSize: number = 0; private typeRecord: Map = new Map(); - private static literalArrayBuffer: Array = []; - private static typeArrayBuffer: Array = new Array(); + private static literalArrayBuffer: Array = new Array(); constructor(internalName: string, parametersCount: number, scope: Scope | undefined = undefined) { this.internalName = internalName; @@ -272,12 +271,10 @@ export class PandaGen { this.typeRecord.set(vreg, type); } - getTypeArrayBuffer() { - return PandaGen.typeArrayBuffer; - } - - appendTypeArrayBuffer(type: BaseType) { - PandaGen.typeArrayBuffer.push(type.transfer2LiteralBuffer()); + static appendTypeArrayBuffer(type: BaseType): number { + let index = PandaGen.literalArrayBuffer.length; + PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); + return index; } getFirstStmt() { diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index e0d8c6fa32..d2df9e7ca0 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -36,7 +36,8 @@ const JsonType = { "record": 1, "string": 2, "literal_arr": 3, - "options": 4 + "options": 4, + "type_arr": 5 }; export class Ts2Panda { static strings: Set = new Set(); diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index f665032c39..d5a92d35f2 100755 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -605,6 +605,7 @@ static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::F if (function.isMember("typeInfo") && function["typeInfo"].isArray()) { auto typeInfo = function["typeInfo"]; panda::pandasm::AnnotationData funcAnnotation("_ESTypeAnnotation"); + std::vector elements; for (Json::ArrayIndex i = 0; i < typeInfo.size(); i++) { auto type = typeInfo[i]; if (!type.isObject()) { @@ -622,10 +623,15 @@ static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::F typeIndex = type["typeIndex"].asUInt(); } - panda::pandasm::AnnotationElement typeOfVregElement(std::to_string(vregNum), std::make_unique(panda::pandasm::ScalarValue::Create(typeIndex))); - funcAnnotation.AddElement(std::move(typeOfVregElement)); + panda::pandasm::ScalarValue vNum(panda::pandasm::ScalarValue::Create(vregNum)); + elements.emplace_back(std::move(vNum)); + panda::pandasm::ScalarValue tIndex(panda::pandasm::ScalarValue::Create(typeIndex)); + elements.emplace_back(std::move(tIndex)); } + std::string annotationName = "typeOfVreg"; + panda::pandasm::AnnotationElement typeOfVregElement(annotationName, std::make_unique(panda::pandasm::ArrayValue(panda::pandasm::Value::Type::U32, elements))); + funcAnnotation.AddElement(std::move(typeOfVregElement)); const_cast&>(pandaFunc.metadata->GetAnnotations()).push_back(std::move(funcAnnotation)); } } -- Gitee From 44c43c8518214d355ff2d19ce0b5cdca03c0470e Mon Sep 17 00:00:00 2001 From: ctw Date: Tue, 28 Sep 2021 19:05:13 +0800 Subject: [PATCH 12/39] add L2 type at the begining of every typeliteralarray Signed-off-by: ctw Change-Id: I3b81893e0fc6d629c56388c42095b41d390fd0ec --- ts2panda/src/base/literal.ts | 2 -- ts2panda/src/base/typeSystem.ts | 14 ++++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ts2panda/src/base/literal.ts b/ts2panda/src/base/literal.ts index b502f5d39d..e246cdc496 100644 --- a/ts2panda/src/base/literal.ts +++ b/ts2panda/src/base/literal.ts @@ -22,8 +22,6 @@ export enum LiteralTag { GENERATOR = 7, ACCESSOR = 8, METHODAFFILIATE = 9, - MODIFIER = 10, - ACCESSFLAG = 11, NULLVALUE = 255 } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index d3b8c48c36..21fe259eb0 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -85,8 +85,9 @@ export class ClassType extends BaseType { transfer2LiteralBuffer() { let classTypeBuf = new LiteralBuffer(); let classTypeLiterals: Array = new Array(); - - classTypeLiterals.push(new Literal(LiteralTag.MODIFIER, this.modifier)); // modifier is added at the front + // the first element is to determine the L2 type + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASS)); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded this.heritages.forEach(heritage => { @@ -96,8 +97,8 @@ export class ClassType extends BaseType { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.fields.size)); // num of fields are recorded this.fields.forEach((typeInfo, name) => { classTypeLiterals.push(new Literal(LiteralTag.STRING, name)); - classTypeLiterals.push(new Literal(LiteralTag.MODIFIER, typeInfo[0])); - classTypeLiterals.push(new Literal(LiteralTag.ACCESSFLAG, typeInfo[1])); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[0])); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[1])); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); }); @@ -128,8 +129,9 @@ export class FunctionType extends BaseType { transfer2LiteralBuffer() : LiteralBuffer { let funcTypeBuf = new LiteralBuffer(); let funcTypeLiterals: Array = new Array(); - funcTypeLiterals.push(new Literal(LiteralTag.ACCESSFLAG, this.accessFlag)); - funcTypeLiterals.push(new Literal(LiteralTag.MODIFIER, this.modifier)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.FUNCTION)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); -- Gitee From e8cc630c3ac6239a478cf495b65ae3fe519a8e32 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 28 Sep 2021 20:33:09 +0800 Subject: [PATCH 13/39] Add class type recording support Signed-off-by: zhuoli Change-Id: Ica3a37da235f92637f1bdf86979a339229be84d2 --- ts2panda/src/base/typeSystem.ts | 285 ++++++++++++++++++++++++++++---- ts2panda/src/index.ts | 4 +- ts2panda/src/recorder.ts | 4 +- ts2panda/src/typeChecker.ts | 2 +- ts2panda/src/typeRecorder.ts | 50 ++++-- 5 files changed, 298 insertions(+), 47 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 21fe259eb0..1ca80af201 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -19,13 +19,19 @@ import { LiteralBuffer, LiteralTag } from "./literal"; +import { TypeChecker } from "../typeChecker"; +import { TypeRecorder } from "../typeRecorder"; +import { TryStatement } from "src/statement/tryStatement"; export enum PremitiveType { - UNDEFINED, - STRING, NUMBER, BOOLEAN, - _LENGTH + STRING, + SYMBOL, + VOID, + NULL, + UNDEFINED, + _LENGTH = 50 } export enum L2Type { @@ -35,24 +41,134 @@ export enum L2Type { } export abstract class BaseType { + abstract transfer2LiteralBuffer(): LiteralBuffer; + protected typeChecker = TypeChecker.getInstance().getTypeChecker(); + protected typeRecorder = TypeRecorder.getInstance(); + + protected getTypePosForIdentifier(node: ts.Node): number { + let identifierSymbol = this.typeChecker.getTypeAtLocation(node).symbol; + return identifierSymbol.declarations[0].pos; + } + + protected getTypeNodeForIdentifier(node: ts.Node): ts.Node { + let identifierSymbol = this.typeChecker.getTypeAtLocation(node).symbol; + return identifierSymbol.declarations[0]; + } + + protected getTypeFlagsForIdentifier(node: ts.Node): string { + let typeFlag = this.typeChecker.getTypeAtLocation(node).getFlags(); + return ts.TypeFlags[typeFlag].toUpperCase(); + } + + protected addCurrentType(node: ts.Node, index: number) { + let typePos = node.pos; + this.typeRecorder.addType2Index(typePos, index); + } + + protected setVariable2Type(variablePos: number, index: number) { + this.typeRecorder.setVariable2Type(variablePos, index); + } + + protected createType(node: ts.Node, variablePos?: number) { + switch(node.kind) { + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.Constructor: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: { + new FunctionType(node, variablePos); + break; + } + case ts.SyntaxKind.ClassDeclaration: { + new ClassType(node, variablePos); + break; + } + } + } + + protected getOrCreateUserDefinedType(node: ts.Node, variablePos?:number) { + let typePos = this.getTypePosForIdentifier(node); + let typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + if (typeIndex == -1) { + let typeNode = this.getTypeNodeForIdentifier(node); + this.createType(typeNode, variablePos); + typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + } + return typeIndex; + } + + protected getTypeIndexForDeclWithType(node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variablePos?: number): number { + if (node.type) { + let typeRef = node.type; + let typeFlagName = this.getTypeFlagsForIdentifier(typeRef); + let typeIndex = -1; + if (typeFlagName in PremitiveType) { + typeIndex = PremitiveType[typeFlagName as keyof typeof PremitiveType]; + } else { + let identifier = typeRef.getChildAt(0); + typeIndex = this.getOrCreateUserDefinedType(identifier, variablePos); + } + // set variable if variablePos is given; + if (variablePos) { + this.setVariable2Type(variablePos, typeIndex); + } + if (typeIndex == -1) { + console.log("ERROR: Type cannot be found for: " + node.getText()); + } + return typeIndex!; + } + // console.trace(); + console.log("WARNING: node type not found for: " + node.getText()); + return -1; + } + + // temp for test + protected getIndex() { + let currIndex = this.typeRecorder.index; + this.typeRecorder.index += 1; + return currIndex; + } + + protected getLog(node: ts.Node) { + // console.log("=========== " + node.kind); + // console.log(node.getText()); + // console.log("=============================="); + // console.log("type2Index: "); + // console.log(this.typeRecorder.getType2Index()); + // console.log("variable2Type: "); + // console.log(this.typeRecorder.getVariable2Type()); + } } export class ClassType extends BaseType { modifier: number = 0; // 0 -> unabstract, 1 -> abstract; heritages: Array = new Array(); - fields : Map> = new Map>(); // Array: [type][static][public/private] + // fileds Array: [typeIndex] [static -> 1] [public -> 0, private -> 1, protected -> 2] [readonly -> 1] + fields: Map> = new Map>(); methods: Array = new Array(); - constructor(classNode: ts.ClassDeclaration) { + constructor(classNode: ts.ClassDeclaration, variablePos?: number) { super(); + + let currIndex = this.getIndex(); + // record type before its initialization, so its index can be recorded + // in case there's recursive reference of this type + this.addCurrentType(classNode, currIndex); + this.fillInModifiers(classNode); this.fillInHeritages(classNode); - this.fillInFields(classNode); - this.fillInMethods(classNode); + this.fillInFieldsAndMethods(classNode); + + // initialization finished, add variable to type if variable is given + if (variablePos) { + this.setVariable2Type(variablePos, currIndex); + } + + // check typeRecorder + this.getLog(classNode); } - fillInModifiers(node: ts.ClassDeclaration) { + private fillInModifiers(node: ts.ClassDeclaration) { if (node.modifiers) { for (let modifier of node.modifiers) { switch (modifier.kind) { @@ -68,18 +184,74 @@ export class ClassType extends BaseType { } } - fillInHeritages(node: ts.ClassDeclaration) { + private fillInHeritages(node: ts.ClassDeclaration) { if (node.heritageClauses) { - + for (let heritage of node.heritageClauses) { + let heritageIdentifier = heritage.getChildAt(1).getChildAt(0); + let heritageTypePos = this.getOrCreateUserDefinedType(heritageIdentifier); + this.heritages.push(heritageTypePos); + } } } - fillInFields(node: ts.ClassDeclaration) { - + private fillInFields(member: ts.PropertyDeclaration) { + // collect modifier info + let fieldName = member.name.getText(); + let fieldInfo = Array(0, 0, 0, 0); + if (member.modifiers) { + for (let modifier of member.modifiers) { + switch(modifier.kind) { + case ts.SyntaxKind.StaticKeyword: { + fieldInfo[1] = 1; + break; + } + case ts.SyntaxKind.PrivateKeyword: { + fieldInfo[2] = 1; + break; + } + case ts.SyntaxKind.ProtectedKeyword: { + fieldInfo[2] = 2; + } + case ts.SyntaxKind.ReadonlyKeyword: { + fieldInfo[3] = 1; + } + } + } + } + // collect type info + let variablePos = member.name? member.name.pos : member.pos; + fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variablePos); + this.fields.set(fieldName, fieldInfo); } - fillInMethods(node: ts.ClassDeclaration) { - + private fillInFieldsAndMethods(node: ts.ClassDeclaration) { + if (node.members) { + for (let member of node.members) { + switch(member.kind) { + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.Constructor: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: { + // a method like declaration in class must be a new type, + // add it into typeRecorder + let typePos = member.pos; + let variablePos = member.name ? member.name.pos : member.pos; + let typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + if (typeIndex == -1) { + this.createType(member, variablePos) + } + // Then, get the typeIndex and fill in the methods array + typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + this.methods.push(typeIndex!); + break; + } + case ts.SyntaxKind.PropertyDeclaration: { + this.fillInFields(member); + break; + } + } + } + } } transfer2LiteralBuffer() { @@ -89,10 +261,10 @@ export class ClassType extends BaseType { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASS)); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded - this.heritages.forEach(heritage => { - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); - }); + // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded + // this.heritages.forEach(heritage => { + // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); + // }); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.fields.size)); // num of fields are recorded this.fields.forEach((typeInfo, name) => { @@ -102,28 +274,81 @@ export class ClassType extends BaseType { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); }); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded - this.fields.forEach(method => { - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); - }); + // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded + // this.fields.forEach(method => { + // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); + // }); - classTypeBuf.addLiterals(...classTypeLiterals); + // classTypeBuf.addLiterals(...classTypeLiterals); return classTypeBuf; } } export class FunctionType extends BaseType { - accessFlag: number = 0; // 0 -> private, 1 -> public + name: string | undefined = ''; + accessFlag: number = 0; // 0 -> public -> 0, private -> 1, protected -> 2 modifier: number = 0; // 0 -> unstatic, 1 -> static - name: string = ''; parameters: Array = new Array(); returnType: number = 0; - constructor(funcNode: ts.FunctionLikeDeclaration) { + constructor(funcNode: ts.FunctionLikeDeclaration, variablePos?: number) { super(); - // pls extract function info here + let currIndex = this.getIndex(); + // record type before its initialization, so its index can be recorded + // in case there's recursive reference of this type + this.addCurrentType(funcNode, currIndex); + + this.name = funcNode.name?.getText(); + this.fillInModifiers(funcNode); + this.fillInParameters(funcNode); + this.fillInReturn(funcNode); + + // initialization finished, add variable to type if variable is given + if (variablePos) { + this.setVariable2Type(variablePos, currIndex); + } + + // check typeRecorder + this.getLog(funcNode); + } + + private fillInModifiers(node: ts.FunctionLikeDeclaration) { + if (node.modifiers) { + for (let modifier of node.modifiers) { + switch (modifier.kind) { + case ts.SyntaxKind.PrivateKeyword: { + this.accessFlag = 1; + break; + } + case ts.SyntaxKind.ProtectedKeyword: { + this.accessFlag = 2; + break; + } + case ts.SyntaxKind.StaticKeyword: { + this.modifier = 1; + } + } + } + } + } + + private fillInParameters(node: ts.FunctionLikeDeclaration) { + if (node.parameters) { + for (let parameter of node.parameters) { + let variableName = parameter.pos; + let typeIndex = this.getTypeIndexForDeclWithType(parameter, variableName); + this.parameters.push(typeIndex); + } + } + } + + private fillInReturn(node: ts.FunctionLikeDeclaration) { + let typeIndex = this.getTypeIndexForDeclWithType(node); + if (typeIndex != -1) { + this.returnType = typeIndex; + } } transfer2LiteralBuffer() : LiteralBuffer { @@ -139,9 +364,9 @@ export class FunctionType extends BaseType { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); }); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); + // funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); - funcTypeBuf.addLiterals(...funcTypeLiterals); + // funcTypeBuf.addLiterals(...funcTypeLiterals); return funcTypeBuf; } } @@ -171,4 +396,4 @@ export class TypeOfVreg { this.vregNum = vregNum; this.typeIndex = typeIndex; } -} \ No newline at end of file +} diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index fb3c296e57..bede719fe2 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -25,10 +25,12 @@ import { RegAlloc } from "./regAllocator"; import { setGlobalStrict } from "./strictMode"; import jshelpers = require("./jshelpers"); import { TypeChecker } from "./typeChecker"; +import { TypeRecorder } from "./typeRecorder"; function main(fileNames: string[], options: ts.CompilerOptions) { let program = ts.createProgram(fileNames, options); let typeChecker = TypeChecker.getInstance(); + TypeRecorder.createInstance(); typeChecker.setTypeChecker(program.getTypeChecker()); let emitResult = program.emit( undefined, @@ -36,7 +38,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { undefined, undefined, { - after: [ + before: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { let outputBinName = CmdOptions.getOutputBinName(); diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index c62e0ceb0b..9919051201 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -50,6 +50,8 @@ import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; import { TypeChecker } from "./typeChecker"; +// test +import { ClassType } from "./base/typeSystem"; export class Recorder { node: ts.Node; @@ -63,7 +65,6 @@ export class Recorder { private importStmts: Array = []; private exportStmts: Array = []; private defaultUsed: boolean = false; - private recordTypeContent: boolean = false; constructor(node: ts.Node, scope: Scope, compilerDriver: CompilerDriver) { this.node = node; @@ -131,6 +132,7 @@ export class Recorder { case ts.SyntaxKind.ClassDeclaration: case ts.SyntaxKind.ClassExpression: { this.recordClassInfo(childNode, scope); + let testClassType = new ClassType(childNode); break; } case ts.SyntaxKind.Identifier: { diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index 3873e5fd08..1918bacd08 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -30,7 +30,7 @@ export class TypeChecker { decList.declarations.forEach(declaration => { const nameNode = declaration.name; let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); - console.log(type.getSymbol()?.valueDeclaration); + // console.log(type.getSymbol()?.valueDeclaration); }) } } diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index 940757a69f..bd1bf7d0e1 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -19,35 +19,57 @@ import { } from "./base/typeSystem"; export class TypeRecorder { - private type2Index: Map = new Map(); + private static instance: TypeRecorder; + private type2Index: Map = new Map(); private typeInfo: Array = new Array(); - private index: number; + private variable2Type: Map = new Map(); - constructor() { + // temp for test index + public index: number; + + private constructor() { this.index = PremitiveType._LENGTH; } - setType2Index(typePosition: string) { - this.type2Index.set(typePosition, this.index); + public static getInstance() { + return TypeRecorder.instance; + } + + public static createInstance() { + TypeRecorder.instance = new TypeRecorder(); + } + + public addType2Index(typePosition: number, index: number) { + this.type2Index.set(typePosition, index); } - setTypeInfo(typeInfo: BaseType) { - this.typeInfo[this.index] = typeInfo; + public setVariable2Type(variablePos: number, index: number) { + this.variable2Type.set(variablePos, index); } - addType(typePosition: string, typeInfo: BaseType) { - this.setType2Index(typePosition); - this.setTypeInfo(typeInfo); - this.index += this.index; + public hasType(typePosition: number): boolean { + return this.type2Index.has(typePosition); } - getType2Index(): Map { + public tryGetTypeIndex(typePosition: number): number { + if (this.type2Index.has(typePosition)) { + return this.type2Index.get(typePosition)!; + } else { + return -1; + } + } + + // might not needed + + public getType2Index(): Map { return this.type2Index; } - getTypeInfo(): Array { + public getTypeInfo(): Array { return this.typeInfo; } - + public getVariable2Type(): Map { + return this.variable2Type; + } } \ No newline at end of file -- Gitee From be726c4fc2128abd33995a787a34cde77c22121c Mon Sep 17 00:00:00 2001 From: ctw Date: Tue, 28 Sep 2021 21:03:17 +0800 Subject: [PATCH 14/39] add readonly for class type in the corresponding type literal buffer Signed-off-by: ctw Change-Id: I1773f2e952f7c5baeb059f070b142c5410f0dbc6 --- ts2panda/src/base/typeSystem.ts | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 1ca80af201..f5bf100f83 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -261,25 +261,26 @@ export class ClassType extends BaseType { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASS)); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); - // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded - // this.heritages.forEach(heritage => { - // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); - // }); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded + this.heritages.forEach(heritage => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); + }); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.fields.size)); // num of fields are recorded this.fields.forEach((typeInfo, name) => { classTypeLiterals.push(new Literal(LiteralTag.STRING, name)); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[0])); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[1])); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[0])); // typeIndex + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[1])); // static + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); // accessFlag + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[3])); // readonly }); - // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded - // this.fields.forEach(method => { - // classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); - // }); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded + this.fields.forEach(method => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); + }); - // classTypeBuf.addLiterals(...classTypeLiterals); + classTypeBuf.addLiterals(...classTypeLiterals); return classTypeBuf; } @@ -364,9 +365,9 @@ export class FunctionType extends BaseType { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); }); - // funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); - // funcTypeBuf.addLiterals(...funcTypeLiterals); + funcTypeBuf.addLiterals(...funcTypeLiterals); return funcTypeBuf; } } -- Gitee From a12f18dee4a7c9f4d45c99d8a29a93bd11bd7a13 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 28 Sep 2021 21:41:13 +0800 Subject: [PATCH 15/39] use typeIndex generated from pandaGen Signed-off-by: zhuoli Change-Id: I7e3ea5c1856e1969fb92c6e7a1a11a4086f2d181 --- ts2panda/src/addVariable2Scope.ts | 5 +++- ts2panda/src/base/typeSystem.ts | 49 +++++++++++++++++++++---------- ts2panda/src/pandagen.ts | 6 +++- ts2panda/src/variable.ts | 2 +- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 8ecc7a1d3f..3b529dcc23 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -80,6 +80,8 @@ export function addVariableToScope(recorder: Recorder) { hoistDecls = hoistMap.get(scope); if (hoistDecls) { hoistDecls.forEach(hoistDecl => { + // console.log("/////// hoist pos ////////// - "); + // console.log(hoistDecl.node.pos); if (hoistDecl instanceof VarDecl) { scope.add(hoistDecl.name, VarDeclarationKind.VAR); } else if (hoistDecl instanceof FuncDecl) { @@ -100,7 +102,8 @@ export function addVariableToScope(recorder: Recorder) { if (hoistDecls && hoistDecls.includes(decl)) { continue; } - + // console.log("/////// decls pos ////////// - "); + // console.log(decl.node.pos); if (decl instanceof LetDecl) { scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); } else if (decl instanceof ConstDecl) { diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index f5bf100f83..2211d5c695 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -21,6 +21,7 @@ import { } from "./literal"; import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; +import { PandaGen } from "../pandagen"; import { TryStatement } from "src/statement/tryStatement"; export enum PremitiveType { @@ -97,7 +98,8 @@ export abstract class BaseType { return typeIndex; } - protected getTypeIndexForDeclWithType(node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variablePos?: number): number { + protected getTypeIndexForDeclWithType( + node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variablePos?: number): number { if (node.type) { let typeRef = node.type; let typeFlagName = this.getTypeFlagsForIdentifier(typeRef); @@ -122,6 +124,14 @@ export abstract class BaseType { return -1; } + protected getIndexFromTypeArrayBuffer(type: BaseType): number { + return PandaGen.appendTypeArrayBuffer(new PlaceHolderType); + } + + protected setTypeArrayBuffer(type: BaseType, index:number) { + PandaGen.setTypeArrayBuffer(type, index); + } + // temp for test protected getIndex() { let currIndex = this.typeRecorder.index; @@ -129,14 +139,23 @@ export abstract class BaseType { return currIndex; } - protected getLog(node: ts.Node) { - // console.log("=========== " + node.kind); - // console.log(node.getText()); - // console.log("=============================="); - // console.log("type2Index: "); - // console.log(this.typeRecorder.getType2Index()); - // console.log("variable2Type: "); - // console.log(this.typeRecorder.getVariable2Type()); + protected getLog(node: ts.Node, currIndex: number) { + console.log("=========== " + node.kind); + console.log(node.getText()); + console.log("=============================="); + console.log("+++++++++++++++++++++++++++++++++"); + console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); + console.log("+++++++++++++++++++++++++++++++++"); + console.log("type2Index: "); + console.log(this.typeRecorder.getType2Index()); + console.log("variable2Type: "); + console.log(this.typeRecorder.getVariable2Type()); + } +} + +export class PlaceHolderType extends BaseType { + transfer2LiteralBuffer(): LiteralBuffer { + return new LiteralBuffer(); } } @@ -150,7 +169,7 @@ export class ClassType extends BaseType { constructor(classNode: ts.ClassDeclaration, variablePos?: number) { super(); - let currIndex = this.getIndex(); + let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(classNode, currIndex); @@ -163,9 +182,9 @@ export class ClassType extends BaseType { if (variablePos) { this.setVariable2Type(variablePos, currIndex); } - + this.setTypeArrayBuffer(this, currIndex); // check typeRecorder - this.getLog(classNode); + this.getLog(classNode, currIndex); } private fillInModifiers(node: ts.ClassDeclaration) { @@ -296,7 +315,7 @@ export class FunctionType extends BaseType { constructor(funcNode: ts.FunctionLikeDeclaration, variablePos?: number) { super(); - let currIndex = this.getIndex(); + let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(funcNode, currIndex); @@ -310,9 +329,10 @@ export class FunctionType extends BaseType { if (variablePos) { this.setVariable2Type(variablePos, currIndex); } + this.setTypeArrayBuffer(this, currIndex); // check typeRecorder - this.getLog(funcNode); + this.getLog(funcNode, currIndex); } private fillInModifiers(node: ts.FunctionLikeDeclaration) { @@ -366,7 +386,6 @@ export class FunctionType extends BaseType { }); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); - funcTypeBuf.addLiterals(...funcTypeLiterals); return funcTypeBuf; } diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index cd0f259fbd..7cea6a085d 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -272,11 +272,15 @@ export class PandaGen { } static appendTypeArrayBuffer(type: BaseType): number { - let index = PandaGen.literalArrayBuffer.length; + let index = PandaGen.literalArrayBuffer.length + 50; PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); return index; } + static setTypeArrayBuffer(type: BaseType, index: number) { + PandaGen.literalArrayBuffer[index] = type.transfer2LiteralBuffer(); + } + getFirstStmt() { return this.firstStmt; } diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index ccf444cf5d..365ec9cac1 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -44,7 +44,7 @@ export abstract class Variable { this.name = name; this.vreg = undefined; this.name = name; - this.typeIndex = PremitiveType.UNDEFINED; + this.typeIndex = -1; } bindVreg(vreg: VReg) { -- Gitee From 6274e5e8c5749079fdfb8553bb436b00916a06b9 Mon Sep 17 00:00:00 2001 From: ctw Date: Wed, 29 Sep 2021 11:27:27 +0800 Subject: [PATCH 16/39] fix store to pandafile Signed-off-by: ctw Change-Id: I05c047b4180069ebb0aea08d2563c68e68fe2f4a --- ts2panda/src/base/typeSystem.ts | 21 ++++++++++----------- ts2panda/src/pandagen.ts | 13 ------------- ts2panda/src/ts2panda.ts | 8 +++++--- ts2panda/src/variable.ts | 2 +- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 2211d5c695..dbb5ca453d 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -22,7 +22,6 @@ import { import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; import { PandaGen } from "../pandagen"; -import { TryStatement } from "src/statement/tryStatement"; export enum PremitiveType { NUMBER, @@ -72,7 +71,7 @@ export abstract class BaseType { } protected createType(node: ts.Node, variablePos?: number) { - switch(node.kind) { + switch (node.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: @@ -87,7 +86,7 @@ export abstract class BaseType { } } - protected getOrCreateUserDefinedType(node: ts.Node, variablePos?:number) { + protected getOrCreateUserDefinedType(node: ts.Node, variablePos?: number) { let typePos = this.getTypePosForIdentifier(node); let typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); if (typeIndex == -1) { @@ -128,7 +127,7 @@ export abstract class BaseType { return PandaGen.appendTypeArrayBuffer(new PlaceHolderType); } - protected setTypeArrayBuffer(type: BaseType, index:number) { + protected setTypeArrayBuffer(type: BaseType, index: number) { PandaGen.setTypeArrayBuffer(type, index); } @@ -219,7 +218,7 @@ export class ClassType extends BaseType { let fieldInfo = Array(0, 0, 0, 0); if (member.modifiers) { for (let modifier of member.modifiers) { - switch(modifier.kind) { + switch (modifier.kind) { case ts.SyntaxKind.StaticKeyword: { fieldInfo[1] = 1; break; @@ -238,7 +237,7 @@ export class ClassType extends BaseType { } } // collect type info - let variablePos = member.name? member.name.pos : member.pos; + let variablePos = member.name ? member.name.pos : member.pos; fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variablePos); this.fields.set(fieldName, fieldInfo); } @@ -246,7 +245,7 @@ export class ClassType extends BaseType { private fillInFieldsAndMethods(node: ts.ClassDeclaration) { if (node.members) { for (let member of node.members) { - switch(member.kind) { + switch (member.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: @@ -295,7 +294,7 @@ export class ClassType extends BaseType { }); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded - this.fields.forEach(method => { + this.methods.forEach(method => { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); }); @@ -320,7 +319,7 @@ export class FunctionType extends BaseType { // in case there's recursive reference of this type this.addCurrentType(funcNode, currIndex); - this.name = funcNode.name?.getText(); + this.name = funcNode.name ?.getText(); this.fillInModifiers(funcNode); this.fillInParameters(funcNode); this.fillInReturn(funcNode); @@ -372,7 +371,7 @@ export class FunctionType extends BaseType { } } - transfer2LiteralBuffer() : LiteralBuffer { + transfer2LiteralBuffer(): LiteralBuffer { let funcTypeBuf = new LiteralBuffer(); let funcTypeLiterals: Array = new Array(); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.FUNCTION)); @@ -401,7 +400,7 @@ export class ObjectLiteralType extends BaseType { // TODO extract object info here } - transfer2LiteralBuffer() : LiteralBuffer { + transfer2LiteralBuffer(): LiteralBuffer { let objTypeBuf = new LiteralBuffer(); return objTypeBuf; diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 7cea6a085d..29b89c0b04 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -202,7 +202,6 @@ export class PandaGen { private sourceFileDebugInfo: string = ""; private sourceCodeDebugInfo: string | undefined; private icSize: number = 0; - private typeRecord: Map = new Map(); private static literalArrayBuffer: Array = new Array(); @@ -259,18 +258,6 @@ export class PandaGen { this.icSize = total; } - getTypeRecord() { - return this.typeRecord; - } - - appendTypeRecord(vreg: VReg, type: number) { - if (this.typeRecord.has(vreg)) { - throw new Error("The vreg has been recorded, please check"); - } - - this.typeRecord.set(vreg, type); - } - static appendTypeArrayBuffer(type: BaseType): number { let index = PandaGen.literalArrayBuffer.length + 50; PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index d2df9e7ca0..3613e0eaa0 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -172,11 +172,13 @@ export class Ts2Panda { let funcSignature = Ts2Panda.getFuncSignature(pg); let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); - let typeRecord = pg.getTypeRecord(); + let typeRecord = pg.getLocals(); let typeInfo = new Array(); - typeRecord.forEach((type, vreg) => { - let typeOfVreg = new TypeOfVreg(vreg.num, type); + typeRecord.forEach((vreg) => { + console.log("Reg num:", vreg.num); + console.log("Reg index:", vreg.getTypeIndex()); + let typeOfVreg = new TypeOfVreg(vreg.num, vreg.getTypeIndex()); typeInfo.push(typeOfVreg); }); diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 365ec9cac1..0a1a16af27 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -44,7 +44,7 @@ export abstract class Variable { this.name = name; this.vreg = undefined; this.name = name; - this.typeIndex = -1; + this.typeIndex = 0; } bindVreg(vreg: VReg) { -- Gitee From d0a78c17c4dbdcc9d99d8573d54deface7d28231 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 28 Sep 2021 21:41:13 +0800 Subject: [PATCH 17/39] fix adding typeIndex to variable Signed-off-by: zhuoli Change-Id: I7e3ea5c1856e1969fb92c6e7a1a11a4086f2d181 --- ts2panda/src/addVariable2Scope.ts | 9 +++++- ts2panda/src/base/typeSystem.ts | 46 +++++++++++++++++++++---------- ts2panda/src/pandagen.ts | 26 +++++++++-------- ts2panda/src/recorder.ts | 3 -- ts2panda/src/ts2panda.ts | 6 ++-- ts2panda/src/typeChecker.ts | 3 ++ 6 files changed, 61 insertions(+), 32 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 8ecc7a1d3f..8316c1b977 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -80,6 +80,8 @@ export function addVariableToScope(recorder: Recorder) { hoistDecls = hoistMap.get(scope); if (hoistDecls) { hoistDecls.forEach(hoistDecl => { + console.log("/////// hoist pos ////////// - "); + console.log(hoistDecl.node.pos); if (hoistDecl instanceof VarDecl) { scope.add(hoistDecl.name, VarDeclarationKind.VAR); } else if (hoistDecl instanceof FuncDecl) { @@ -100,7 +102,8 @@ export function addVariableToScope(recorder: Recorder) { if (hoistDecls && hoistDecls.includes(decl)) { continue; } - + console.log("/////// decls pos ////////// - "); + console.log(decl.node.pos); if (decl instanceof LetDecl) { scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); } else if (decl instanceof ConstDecl) { @@ -138,6 +141,8 @@ export function addVariableToScope(recorder: Recorder) { } function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): void { + console.log("////////// func //////////"); + console.log(node.pos); let patternParams: Array = new Array(); for (let i = 0; i < node.parameters.length; ++i) { let param = node.parameters[i]; @@ -148,6 +153,8 @@ function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): } else if (ts.isIdentifier(param.name)) { name = jshelpers.getTextOfIdentifierOrLiteral(param.name); } + console.log("//////// add para /////////"); + console.log(param.pos); scope.addParameter(name, VarDeclarationKind.VAR, i + 1); } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index f5bf100f83..07fa998046 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -21,6 +21,7 @@ import { } from "./literal"; import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; +import { PandaGen } from "../pandagen"; import { TryStatement } from "src/statement/tryStatement"; export enum PremitiveType { @@ -122,6 +123,14 @@ export abstract class BaseType { return -1; } + protected getIndexFromTypeArrayBuffer(type: BaseType): number { + return PandaGen.appendTypeArrayBuffer(new PlaceHolderType); + } + + protected setTypeArrayBuffer(type: BaseType, index:number) { + PandaGen.setTypeArrayBuffer(type, index); + } + // temp for test protected getIndex() { let currIndex = this.typeRecorder.index; @@ -129,14 +138,23 @@ export abstract class BaseType { return currIndex; } - protected getLog(node: ts.Node) { - // console.log("=========== " + node.kind); - // console.log(node.getText()); - // console.log("=============================="); - // console.log("type2Index: "); - // console.log(this.typeRecorder.getType2Index()); - // console.log("variable2Type: "); - // console.log(this.typeRecorder.getVariable2Type()); + protected getLog(node: ts.Node, currIndex: number) { + console.log("=========== " + node.kind); + console.log(node.getText()); + console.log("=============================="); + console.log("+++++++++++++++++++++++++++++++++"); + console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); + console.log("+++++++++++++++++++++++++++++++++"); + console.log("type2Index: "); + console.log(this.typeRecorder.getType2Index()); + console.log("variable2Type: "); + console.log(this.typeRecorder.getVariable2Type()); + } +} + +export class PlaceHolderType extends BaseType { + transfer2LiteralBuffer(): LiteralBuffer { + return new LiteralBuffer(); } } @@ -150,7 +168,7 @@ export class ClassType extends BaseType { constructor(classNode: ts.ClassDeclaration, variablePos?: number) { super(); - let currIndex = this.getIndex(); + let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(classNode, currIndex); @@ -163,9 +181,9 @@ export class ClassType extends BaseType { if (variablePos) { this.setVariable2Type(variablePos, currIndex); } - + this.setTypeArrayBuffer(this, currIndex); // check typeRecorder - this.getLog(classNode); + this.getLog(classNode, currIndex); } private fillInModifiers(node: ts.ClassDeclaration) { @@ -296,7 +314,7 @@ export class FunctionType extends BaseType { constructor(funcNode: ts.FunctionLikeDeclaration, variablePos?: number) { super(); - let currIndex = this.getIndex(); + let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(funcNode, currIndex); @@ -310,9 +328,10 @@ export class FunctionType extends BaseType { if (variablePos) { this.setVariable2Type(variablePos, currIndex); } + this.setTypeArrayBuffer(this, currIndex); // check typeRecorder - this.getLog(funcNode); + this.getLog(funcNode, currIndex); } private fillInModifiers(node: ts.FunctionLikeDeclaration) { @@ -366,7 +385,6 @@ export class FunctionType extends BaseType { }); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); - funcTypeBuf.addLiterals(...funcTypeLiterals); return funcTypeBuf; } diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index cd0f259fbd..6da7ed9c6a 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -202,7 +202,7 @@ export class PandaGen { private sourceFileDebugInfo: string = ""; private sourceCodeDebugInfo: string | undefined; private icSize: number = 0; - private typeRecord: Map = new Map(); + // private typeRecord: Map = new Map(); private static literalArrayBuffer: Array = new Array(); @@ -259,24 +259,28 @@ export class PandaGen { this.icSize = total; } - getTypeRecord() { - return this.typeRecord; - } + // getTypeRecord() { + // return this.typeRecord; + // } - appendTypeRecord(vreg: VReg, type: number) { - if (this.typeRecord.has(vreg)) { - throw new Error("The vreg has been recorded, please check"); - } + // appendTypeRecord(vreg: VReg, type: number) { + // if (this.typeRecord.has(vreg)) { + // throw new Error("The vreg has been recorded, please check"); + // } - this.typeRecord.set(vreg, type); - } + // this.typeRecord.set(vreg, type); + // } static appendTypeArrayBuffer(type: BaseType): number { - let index = PandaGen.literalArrayBuffer.length; + let index = PandaGen.literalArrayBuffer.length + 50; PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); return index; } + static setTypeArrayBuffer(type: BaseType, index: number) { + PandaGen.literalArrayBuffer[index] = type.transfer2LiteralBuffer(); + } + getFirstStmt() { return this.firstStmt; } diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 9919051201..14db9c4f7a 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -50,8 +50,6 @@ import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; import { TypeChecker } from "./typeChecker"; -// test -import { ClassType } from "./base/typeSystem"; export class Recorder { node: ts.Node; @@ -132,7 +130,6 @@ export class Recorder { case ts.SyntaxKind.ClassDeclaration: case ts.SyntaxKind.ClassExpression: { this.recordClassInfo(childNode, scope); - let testClassType = new ClassType(childNode); break; } case ts.SyntaxKind.Identifier: { diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index d2df9e7ca0..7c1ff602c2 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -172,11 +172,11 @@ export class Ts2Panda { let funcSignature = Ts2Panda.getFuncSignature(pg); let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); - let typeRecord = pg.getTypeRecord(); + let typeRecord = pg.getLocals(); let typeInfo = new Array(); - typeRecord.forEach((type, vreg) => { - let typeOfVreg = new TypeOfVreg(vreg.num, type); + typeRecord.forEach((vreg) => { + let typeOfVreg = new TypeOfVreg(vreg.num, vreg.getTypeIndex()); typeInfo.push(typeOfVreg); }); diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index 1918bacd08..edc41d0c38 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -1,4 +1,5 @@ import ts from "typescript"; +import { ClassType } from "./base/typeSystem"; export class TypeChecker { private static instance: TypeChecker; @@ -30,6 +31,8 @@ export class TypeChecker { decList.declarations.forEach(declaration => { const nameNode = declaration.name; let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); + let targetNode = type.getSymbol()?.valueDeclaration; + let testClassType = new ClassType(targetNode); // console.log(type.getSymbol()?.valueDeclaration); }) } -- Gitee From ba8bd5bd48898f14413ef7d48ba2a3b37a39d7a8 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 29 Sep 2021 15:29:44 +0800 Subject: [PATCH 18/39] 1. add typeIndex to variable in "addType2Scope" 2. fix missing recursive for VariableStatement in recorder 3. fix typo for PrimitiveType Signed-off-by: zhuoli Change-Id: I51703fb3ecc900bee86c758ec391d09a02711d2e --- ts2panda/src/addVariable2Scope.ts | 52 +++++++++++++++++++++++-------- ts2panda/src/base/typeSystem.ts | 6 ++-- ts2panda/src/index.ts | 3 ++ ts2panda/src/recorder.ts | 2 ++ ts2panda/src/ts2panda.ts | 2 -- ts2panda/src/typeChecker.ts | 6 +++- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 8316c1b977..75971ba114 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -32,7 +32,11 @@ import { VariableScope } from "./scope"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; -import { VarDeclarationKind } from "./variable"; +import { + VarDeclarationKind, + Variable +} from "./variable"; +import { TypeRecorder } from "./typeRecorder"; function addInnerArgs(node: ts.Node, scope: VariableScope): void { @@ -82,13 +86,20 @@ export function addVariableToScope(recorder: Recorder) { hoistDecls.forEach(hoistDecl => { console.log("/////// hoist pos ////////// - "); console.log(hoistDecl.node.pos); + let v: Variable | undefined; if (hoistDecl instanceof VarDecl) { - scope.add(hoistDecl.name, VarDeclarationKind.VAR); + v = scope.add(hoistDecl.name, VarDeclarationKind.VAR); } else if (hoistDecl instanceof FuncDecl) { - scope.add(hoistDecl.name, VarDeclarationKind.FUNCTION); + v = scope.add(hoistDecl.name, VarDeclarationKind.FUNCTION); } else { throw new Error("Wrong type of declaration to be hoisted") } + if (v) { + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex); + } + } }) } } @@ -104,26 +115,27 @@ export function addVariableToScope(recorder: Recorder) { } console.log("/////// decls pos ////////// - "); console.log(decl.node.pos); + let v: Variable | undefined; if (decl instanceof LetDecl) { - scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); + v = scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); } else if (decl instanceof ConstDecl) { - scope.add(decl.name, VarDeclarationKind.CONST, InitStatus.UNINITIALIZED); + v = scope.add(decl.name, VarDeclarationKind.CONST, InitStatus.UNINITIALIZED); } else if (decl instanceof FuncDecl) { - scope.add(decl.name, VarDeclarationKind.FUNCTION); + v = scope.add(decl.name, VarDeclarationKind.FUNCTION); } else if (decl instanceof CatchParameter) { - scope.add(decl.name, VarDeclarationKind.LET); + v = scope.add(decl.name, VarDeclarationKind.LET); } else if (decl instanceof ModDecl) { if (!(scope instanceof ModuleScope)) { throw new Error("ModuleVariable can't exist without ModuleScope"); } - scope.add(decl.name, VarDeclarationKind.MODULE); + v = scope.add(decl.name, VarDeclarationKind.MODULE); } else if (decl instanceof ClassDecl) { let classNode = decl.node; if (ts.isClassDeclaration(classNode)) { - scope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + v = scope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); } else { let classScope = recorder.getScopeOfNode(classNode); - classScope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + v = classScope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); } } else { /** @@ -133,7 +145,14 @@ export function addVariableToScope(recorder: Recorder) { * but it should be added to scope */ if (isGlobalIdentifier(decls[j].name)) { - scope.add(decls[j].name, VarDeclarationKind.VAR); + v = scope.add(decls[j].name, VarDeclarationKind.VAR); + } + } + + if (v) { + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex); } } } @@ -141,7 +160,7 @@ export function addVariableToScope(recorder: Recorder) { } function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): void { - console.log("////////// func //////////"); + console.log("////////// methods //////////"); console.log(node.pos); let patternParams: Array = new Array(); for (let i = 0; i < node.parameters.length; ++i) { @@ -156,7 +175,14 @@ function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): console.log("//////// add para /////////"); console.log(param.pos); - scope.addParameter(name, VarDeclarationKind.VAR, i + 1); + let v = scope.addParameter(name, VarDeclarationKind.VAR, i + 1); + + if (v) { + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex); + } + } } for (let i = 0; i < patternParams.length; i++) { diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index dbb5ca453d..77aff5eb01 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -23,7 +23,7 @@ import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; import { PandaGen } from "../pandagen"; -export enum PremitiveType { +export enum PrimitiveType { NUMBER, BOOLEAN, STRING, @@ -103,8 +103,8 @@ export abstract class BaseType { let typeRef = node.type; let typeFlagName = this.getTypeFlagsForIdentifier(typeRef); let typeIndex = -1; - if (typeFlagName in PremitiveType) { - typeIndex = PremitiveType[typeFlagName as keyof typeof PremitiveType]; + if (typeFlagName in PrimitiveType) { + typeIndex = PrimitiveType[typeFlagName as keyof typeof PrimitiveType]; } else { let identifier = typeRef.getChildAt(0); typeIndex = this.getOrCreateUserDefinedType(identifier, variablePos); diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index bede719fe2..920a8c3ae9 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -41,6 +41,9 @@ function main(fileNames: string[], options: ts.CompilerOptions) { before: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { + const printer: ts.Printer = ts.createPrinter({newLine:ts.NewLineKind.LineFeed}); + const result: string = printer.printNode(ts.EmitHint.Unspecified, node, node); + console.log(result); let outputBinName = CmdOptions.getOutputBinName(); let fileName = node.fileName.substring(0, node.fileName.lastIndexOf('.')); if (fileName != CmdOptions.getInputFileName()) { diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 14db9c4f7a..2fd051ee2e 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -166,6 +166,7 @@ export class Recorder { } case ts.SyntaxKind.VariableStatement: { TypeChecker.getInstance().formatNodeType(childNode); + this.recordInfo(childNode, scope); break; } default: @@ -202,6 +203,7 @@ export class Recorder { let parent = this.getDeclarationNodeOfId(id); if (parent) { + console.log(id.getText()); let declKind = astutils.getVarDeclarationKind(parent); // collect declaration information to corresponding scope diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 3613e0eaa0..7c1ff602c2 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -176,8 +176,6 @@ export class Ts2Panda { let typeInfo = new Array(); typeRecord.forEach((vreg) => { - console.log("Reg num:", vreg.num); - console.log("Reg index:", vreg.getTypeIndex()); let typeOfVreg = new TypeOfVreg(vreg.num, vreg.getTypeIndex()); typeInfo.push(typeOfVreg); }); diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index edc41d0c38..d8e3a642d8 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -32,7 +32,11 @@ export class TypeChecker { const nameNode = declaration.name; let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); let targetNode = type.getSymbol()?.valueDeclaration; - let testClassType = new ClassType(targetNode); + if (targetNode) { + if (ts.isClassDeclaration(targetNode!)) { + let testClassType = new ClassType(targetNode); + } + } // console.log(type.getSymbol()?.valueDeclaration); }) } -- Gitee From 296c2b54f66e929dbf01f2f770cf09e5aab26192 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 29 Sep 2021 15:44:45 +0800 Subject: [PATCH 19/39] fix typo Signed-off-by: zhuoli Change-Id: I4b6cf7cd88894fa415d3131f3ea1d5f73631974c --- ts2panda/src/typeRecorder.ts | 4 ++-- ts2panda/src/variable.ts | 1 - ts2panda/templates/irnodes.ts.erb | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index bd1bf7d0e1..4fa39be07e 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -15,7 +15,7 @@ import { BaseType, - PremitiveType + PrimitiveType } from "./base/typeSystem"; export class TypeRecorder { @@ -28,7 +28,7 @@ export class TypeRecorder { public index: number; private constructor() { - this.index = PremitiveType._LENGTH; + this.index = PrimitiveType._LENGTH; } public static getInstance() { diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 0a1a16af27..88b9b4a79e 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -19,7 +19,6 @@ import { LoopScope, VariableScope } from "./scope"; -import { PremitiveType } from "./base/typeSystem" export enum VarDeclarationKind { NONE, diff --git a/ts2panda/templates/irnodes.ts.erb b/ts2panda/templates/irnodes.ts.erb index 3d06397785..2e73c9cee4 100755 --- a/ts2panda/templates/irnodes.ts.erb +++ b/ts2panda/templates/irnodes.ts.erb @@ -25,7 +25,6 @@ import { NodeKind } from "./debuginfo"; import { LOGE } from "./log" -import { PremitiveType } from "./base/typeSystem" export enum IRNodeKind { VREG, @@ -203,7 +202,7 @@ export class VReg { constructor() { this.id = VReg.global_id++; - this.typeIndex = PremitiveType.UNDEFINED; + this.typeIndex = 0; // for debug purposes this.setStackTrace(null); -- Gitee From 9ad1739957b71b3666567991ce0ad58a77444fbe Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 29 Sep 2021 19:18:29 +0800 Subject: [PATCH 20/39] re-construct function for adding type to variable Signed-off-by: zhuoli Change-Id: I4ebb3abee3f49c242bc6b00e45a80ae07bbb624f --- ts2panda/src/addVariable2Scope.ts | 50 ++++++++++++++++++------------- ts2panda/src/base/typeSystem.ts | 3 +- ts2panda/src/ts2panda.ts | 5 +++- ts2panda/src/typeChecker.ts | 3 +- ts2panda/src/typeRecorder.ts | 9 +++++- ts2panda/src/variable.ts | 2 ++ 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 75971ba114..e5739311df 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -38,6 +38,27 @@ import { } from "./variable"; import { TypeRecorder } from "./typeRecorder"; +function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { + if (v) { + let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(node.pos); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex); + } + console.log("--node.pos--", node.pos); + console.log("--node.type--", v.getTypeIndex()); + } +} + +function setClassOrFunctionType(node: ts.Node, v: Variable | undefined) { + if (v) { + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex); + } + console.log("--node.pos--", node.pos); + console.log("--node.type--", v.getTypeIndex()); + } +} function addInnerArgs(node: ts.Node, scope: VariableScope): void { // the first argument for js function is func_obj @@ -89,17 +110,13 @@ export function addVariableToScope(recorder: Recorder) { let v: Variable | undefined; if (hoistDecl instanceof VarDecl) { v = scope.add(hoistDecl.name, VarDeclarationKind.VAR); + setVariableOrParameterType(hoistDecl.node, v); } else if (hoistDecl instanceof FuncDecl) { v = scope.add(hoistDecl.name, VarDeclarationKind.FUNCTION); + setClassOrFunctionType(hoistDecl.node, v); } else { throw new Error("Wrong type of declaration to be hoisted") } - if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); - if (typeIndex != -1) { - v.setTypeIndex(typeIndex); - } - } }) } } @@ -118,12 +135,16 @@ export function addVariableToScope(recorder: Recorder) { let v: Variable | undefined; if (decl instanceof LetDecl) { v = scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); + setVariableOrParameterType(decl.node, v); } else if (decl instanceof ConstDecl) { v = scope.add(decl.name, VarDeclarationKind.CONST, InitStatus.UNINITIALIZED); + setVariableOrParameterType(decl.node, v); } else if (decl instanceof FuncDecl) { v = scope.add(decl.name, VarDeclarationKind.FUNCTION); + setClassOrFunctionType(decl.node, v); } else if (decl instanceof CatchParameter) { v = scope.add(decl.name, VarDeclarationKind.LET); + setVariableOrParameterType(decl.node, v); } else if (decl instanceof ModDecl) { if (!(scope instanceof ModuleScope)) { throw new Error("ModuleVariable can't exist without ModuleScope"); @@ -133,9 +154,11 @@ export function addVariableToScope(recorder: Recorder) { let classNode = decl.node; if (ts.isClassDeclaration(classNode)) { v = scope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + setClassOrFunctionType(decl.node, v); } else { let classScope = recorder.getScopeOfNode(classNode); v = classScope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + setClassOrFunctionType(decl.node, v); } } else { /** @@ -148,13 +171,6 @@ export function addVariableToScope(recorder: Recorder) { v = scope.add(decls[j].name, VarDeclarationKind.VAR); } } - - if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); - if (typeIndex != -1) { - v.setTypeIndex(typeIndex); - } - } } }) } @@ -176,13 +192,7 @@ function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): console.log(param.pos); let v = scope.addParameter(name, VarDeclarationKind.VAR, i + 1); - - if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); - if (typeIndex != -1) { - v.setTypeIndex(typeIndex); - } - } + setVariableOrParameterType(param, v); } for (let i = 0; i < patternParams.length; i++) { diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 77aff5eb01..291479fedc 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -24,6 +24,7 @@ import { TypeRecorder } from "../typeRecorder"; import { PandaGen } from "../pandagen"; export enum PrimitiveType { + ANY, NUMBER, BOOLEAN, STRING, @@ -142,7 +143,7 @@ export abstract class BaseType { console.log("=========== " + node.kind); console.log(node.getText()); console.log("=============================="); - console.log("+++++++++++++++++++++++++++++++++"); + console.log("+++++++++++ currIndex +++++++++++ - ", currIndex); console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); console.log("+++++++++++++++++++++++++++++++++"); console.log("type2Index: "); diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 7c1ff602c2..648df5825f 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -173,11 +173,14 @@ export class Ts2Panda { let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); let typeRecord = pg.getLocals(); - + console.log("\\\\\\-= funcNmae =-\\\\\\ - ", funcName); let typeInfo = new Array(); typeRecord.forEach((vreg) => { let typeOfVreg = new TypeOfVreg(vreg.num, vreg.getTypeIndex()); typeInfo.push(typeOfVreg); + + console.log("\\\\\\\\\\\\ vreg num \\\\\\\\\\", vreg.num); + console.log("\\\\\\\\\\\\ vreg type \\\\\\\\\\", vreg.getTypeIndex()); }); let variables, sourceCode; diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index d8e3a642d8..d07bd4ce22 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -33,8 +33,9 @@ export class TypeChecker { let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); let targetNode = type.getSymbol()?.valueDeclaration; if (targetNode) { + let variablePos = nameNode.pos; if (ts.isClassDeclaration(targetNode!)) { - let testClassType = new ClassType(targetNode); + let testClassType = new ClassType(targetNode, variablePos); } } // console.log(type.getSymbol()?.valueDeclaration); diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index 4fa39be07e..52b9c18798 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -59,8 +59,15 @@ export class TypeRecorder { } } - // might not needed + public tryGetVariable2Type(variablePosition: number): number { + if (this.variable2Type.has(variablePosition)) { + return this.variable2Type.get(variablePosition)!; + } else { + return -1; + } + } + // might not needed public getType2Index(): Map { return this.type2Index; } diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 88b9b4a79e..67b2a1cee0 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -49,6 +49,8 @@ export abstract class Variable { bindVreg(vreg: VReg) { this.vreg = vreg; this.vreg.setTypeIndex(this.typeIndex); + console.log("==== bindVreg var Name ====: ", this.name); + console.log("==== bindVreg typeIndex ====: ", this.typeIndex); } hasAlreadyBinded(): boolean { -- Gitee From 181361a3472a6e19e9c5c327c1e7a7a9718f8b53 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 29 Sep 2021 20:34:23 +0800 Subject: [PATCH 21/39] fix null buffer in literalArrayBuffer Signed-off-by: zhuoli Change-Id: I24f8d83bccd59d2e022ec75c4b674242b41213c4 --- ts2panda/src/addVariable2Scope.ts | 6 ++++-- ts2panda/src/base/typeSystem.ts | 2 ++ ts2panda/src/pandagen.ts | 2 +- ts2panda/src/ts2panda.ts | 5 +++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index e5739311df..d98b223193 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -37,12 +37,14 @@ import { Variable } from "./variable"; import { TypeRecorder } from "./typeRecorder"; +import { PrimitiveType } from "./base/typeSystem"; + function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { if (v) { let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(node.pos); if (typeIndex != -1) { - v.setTypeIndex(typeIndex); + v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } console.log("--node.pos--", node.pos); console.log("--node.type--", v.getTypeIndex()); @@ -53,7 +55,7 @@ function setClassOrFunctionType(node: ts.Node, v: Variable | undefined) { if (v) { let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); if (typeIndex != -1) { - v.setTypeIndex(typeIndex); + v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } console.log("--node.pos--", node.pos); console.log("--node.type--", v.getTypeIndex()); diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 291479fedc..dd41e0b050 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -230,9 +230,11 @@ export class ClassType extends BaseType { } case ts.SyntaxKind.ProtectedKeyword: { fieldInfo[2] = 2; + break; } case ts.SyntaxKind.ReadonlyKeyword: { fieldInfo[3] = 1; + break; } } } diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 29b89c0b04..76355805f7 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -259,7 +259,7 @@ export class PandaGen { } static appendTypeArrayBuffer(type: BaseType): number { - let index = PandaGen.literalArrayBuffer.length + 50; + let index = PandaGen.literalArrayBuffer.length; PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); return index; } diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 648df5825f..61e13ea2ac 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -135,6 +135,11 @@ export class Ts2Panda { static dumpConstantPool(ts2abc: any): void { let literalArrays = PandaGen.getLiteralArrayBuffer(); + console.log("-=-=-=-length=-=-=-=-=-="); + for (let e of PandaGen.getLiteralArrayBuffer()) { + console.log(JSON.parse(JSON.stringify(e))); + } + if (CmdOptions.isEnableDebugLog()) { Ts2Panda.jsonString += escapeUnicode(JSON.stringify(literalArrays, null, 2)); } -- Gitee From 8465ab7150780de78069a69a65a877b00e31be2a Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Thu, 7 Oct 2021 16:18:31 +0800 Subject: [PATCH 22/39] Modify the transformation of tsc from the before phase to beafter Signed-off-by: zgy-ian --- ts2panda/src/compilerDriver.ts | 4 ++++ ts2panda/src/index.ts | 29 +++++++++++++++++++++++++---- ts2panda/src/recorder.ts | 12 +++++++----- ts2panda/src/syntaxCheckHelper.ts | 4 ++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index e8fa59c596..087cbcd304 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -143,6 +143,10 @@ export class CompilerDriver { return spArray.reverse(); } + compileForSyntaxCheck(node: ts.SourceFile): void { + this.compilePrologue(node); + } + compile(node: ts.SourceFile): void { if (CmdOptions.showASTStatistics()) { let statics: number[] = new Array(ts.SyntaxKind.Count).fill(0); diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index f778f0a75e..47eb54db2b 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -36,11 +36,23 @@ function main(fileNames: string[], options: ts.CompilerOptions) { before: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { - let outputBinName = CmdOptions.getOutputBinName(); - let fileName = node.fileName.substring(0, node.fileName.lastIndexOf('.')); - if (fileName != CmdOptions.getInputFileName()) { - outputBinName = fileName + ".abc"; + let outputBinName = getOutputBinName(node); + let compilerDriver = new CompilerDriver(outputBinName); + compilerDriver.compileForSyntaxCheck(node); + return node; + } + } + ], + after: [ + (ctx: ts.TransformationContext) => { + return (node: ts.SourceFile) => { + if (ts.getEmitHelpers(node)) { + const printer: ts.Printer = ts.createPrinter({newLine:ts.NewLineKind.LineFeed}); + const text: string = printer.printNode(ts.EmitHint.Unspecified, node, node); + let newNode = ts.createSourceFile(node.fileName, text, options.target!); + node = newNode; } + let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); if (CmdOptions.isVariantBytecode()) { @@ -70,6 +82,15 @@ function main(fileNames: string[], options: ts.CompilerOptions) { }); } +function getOutputBinName(node: ts.SourceFile) { + let outputBinName = CmdOptions.getOutputBinName(); + let fileName = node.fileName.substring(0, node.fileName.lastIndexOf('.')); + if (fileName != CmdOptions.getInputFileName()) { + outputBinName = fileName + ".abc"; + } + return outputBinName; +} + namespace Compiler { export namespace Options { export let Default: ts.CompilerOptions = { diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c..391b4b8c4c 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -42,9 +42,7 @@ import { VariableScope } from "./scope"; import { - AddCtor2Class, - isContainConstruct, - getClassNameForConstructor + AddCtor2Class, getClassNameForConstructor, isContainConstruct } from "./statement/classStatement"; import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; @@ -83,6 +81,10 @@ export class Recorder { private recordInfo(node: ts.Node, scope: Scope) { node.forEachChild(childNode => { + if (childNode!.parent == undefined || childNode.parent.kind != node.kind) { + childNode = jshelpers.setParent(childNode, node)!; + childNode = ts.setTextRange(childNode, node)!; + } checkSyntaxError(childNode); switch (childNode.kind) { case ts.SyntaxKind.FunctionExpression: @@ -217,7 +219,7 @@ export class Recorder { let tmp: Scope | undefined = nearestRefVariableScope.getNearestLexicalScope(); let needCreateLoopEnv: boolean = false; if (nearestDefLexicalScope instanceof LoopScope) { - while(tmp) { + while (tmp) { if (tmp == nearestDefLexicalScope) { needCreateLoopEnv = true; break; @@ -236,7 +238,7 @@ export class Recorder { if (name == "arguments") { let varialbeScope = scope.getNearestVariableScope(); - varialbeScope ?.setUseArgs(true); + varialbeScope?.setUseArgs(true); } } diff --git a/ts2panda/src/syntaxCheckHelper.ts b/ts2panda/src/syntaxCheckHelper.ts index 2c719c38f4..8439b27263 100644 --- a/ts2panda/src/syntaxCheckHelper.ts +++ b/ts2panda/src/syntaxCheckHelper.ts @@ -256,6 +256,10 @@ export function isOptionalParameter(node: ts.ParameterDeclaration): boolean { return true; } + if (!node.parent || !node.parent.parent) { + return false; + } + let iife = jshelpers.getImmediatelyInvokedFunctionExpression(node.parent); if (iife) { return !node.type && !node.dotDotDotToken && node.parent.parameters.indexOf(node) >= iife.arguments.length; -- Gitee From 4f20616ea0f1253834fa7f9555d6f92e89273b21 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 8 Oct 2021 14:28:02 +0800 Subject: [PATCH 23/39] minor change of default typeIndex from 0 to 77 Signed-off-by: zhuoli Change-Id: I537c1b91a00232d2a2e28d9e5e91626b68aa2f99 --- ts2panda/src/base/typeSystem.ts | 14 ++++++-------- ts2panda/src/variable.ts | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index dd41e0b050..712d0c0a16 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -140,16 +140,14 @@ export abstract class BaseType { } protected getLog(node: ts.Node, currIndex: number) { - console.log("=========== " + node.kind); + console.log("=========== NodeKind ===========: " + node.kind); console.log(node.getText()); - console.log("=============================="); - console.log("+++++++++++ currIndex +++++++++++ - ", currIndex); + console.log("=========== currIndex ===========: ", currIndex); console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); - console.log("+++++++++++++++++++++++++++++++++"); - console.log("type2Index: "); - console.log(this.typeRecorder.getType2Index()); - console.log("variable2Type: "); - console.log(this.typeRecorder.getVariable2Type()); + console.log("=============================="); + console.log("type2Index: ", this.typeRecorder.getType2Index()); + console.log("variable2Type: ", this.typeRecorder.getVariable2Type()); + console.log("=============================="); } } diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 67b2a1cee0..dc91778d6d 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -43,7 +43,7 @@ export abstract class Variable { this.name = name; this.vreg = undefined; this.name = name; - this.typeIndex = 0; + this.typeIndex = 77; } bindVreg(vreg: VReg) { -- Gitee From 1ab5da0d75844b0a5421cc2c79631cf1948ba95f Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Mon, 27 Sep 2021 16:33:03 +0800 Subject: [PATCH 24/39] =?UTF-8?q?fixed=20e653052=20from=20https://gitee.co?= =?UTF-8?q?m/zgy-ian/ark=5Fts2abc/pulls/44=20=E7=A7=BB=E6=A4=8Dts2abc?= =?UTF-8?q?=E7=9A=84ut=20=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgy-ian --- ts2panda/BUILD.gn | 49 + ts2panda/scripts/run_tests.py | 163 +++ ts2panda/tests/BUILD.gn | 163 +++ ts2panda/tests/builtIns.test.ts | 8 +- ts2panda/tests/expression/arguments.test.ts | 70 + .../tests/{ => expression}/binary.test.ts | 698 ++-------- ts2panda/tests/expression/call.test.ts | 90 +- ts2panda/tests/expression/cmpBinary.test.ts | 335 +++++ .../tests/{ => expression}/conditions.test.ts | 85 +- ts2panda/tests/expression/delete.test.ts | 147 ++ .../{ => expression}/elementAccess.test.ts | 47 +- .../expression/functionExpression.test.ts | 161 +-- .../tests/{ => expression}/literal.test.ts | 256 ++-- ts2panda/tests/expression/logicBinary.test.ts | 79 ++ ts2panda/tests/expression/new.test.ts | 62 +- .../tests/expression/numericLiteral.test.ts | 12 +- .../tests/expression/operationEqual.test.ts | 204 +++ .../tests/expression/parenthesized.test.ts | 53 + .../expression/postfixOperations.test.ts | 72 + .../tests/expression/prefixOperations.test.ts | 155 +++ .../{ => expression}/propertyAccess.test.ts | 57 +- ts2panda/tests/expression/regular.test.js | 50 + .../tests/expression/stringLiteral.test.ts | 4 +- ...ion.test.ts => templateExpression.test.ts} | 128 +- .../thisKeyWord.test.ts} | 208 +-- ts2panda/tests/expression/typeOf.test.ts | 88 ++ ts2panda/tests/expression/void.test.ts | 42 + ts2panda/tests/hoist.test.ts | 93 +- ts2panda/tests/intrinsicExpander.test.ts | 20 +- ts2panda/tests/lexenv.test.ts | 141 +- ts2panda/tests/pandagen.test.ts | 6 +- ts2panda/tests/regAllocator.test.ts | 101 +- ts2panda/tests/scope.test.ts | 48 +- .../debugger.test.ts} | 16 +- ts2panda/tests/statements/doWhile.test.ts | 139 ++ .../{loops.test.ts => statements/for.test.ts} | 1194 +++++------------ ts2panda/tests/statements/forIn.test.ts | 81 +- ts2panda/tests/statements/forOf.test.ts | 305 +++++ .../statements/functionDeclaration.test.ts | 166 +++ .../return.test.ts} | 14 +- ts2panda/tests/statements/switch.test.ts | 75 +- .../tests/{ => statements}/tryCatch.test.ts | 67 +- .../variableDeclaration.test.ts} | 626 ++++----- ts2panda/tests/statements/while.test.ts | 179 +++ ts2panda/tests/strictmode/strictmode.test.ts | 16 +- ts2panda/tests/tsconfig.mac.json | 12 + ts2panda/tests/tsconfig.win.json | 12 + ts2panda/tests/unary.test.ts | 399 ------ ts2panda/tests/utils/asthelper.ts | 2 +- ts2panda/tests/utils/base.ts | 3 +- ts2panda/ts2abc_config.gni | 43 + 51 files changed, 4002 insertions(+), 3242 deletions(-) create mode 100755 ts2panda/scripts/run_tests.py create mode 100644 ts2panda/tests/BUILD.gn create mode 100644 ts2panda/tests/expression/arguments.test.ts rename ts2panda/tests/{ => expression}/binary.test.ts (31%) create mode 100644 ts2panda/tests/expression/cmpBinary.test.ts rename ts2panda/tests/{ => expression}/conditions.test.ts (76%) create mode 100644 ts2panda/tests/expression/delete.test.ts rename ts2panda/tests/{ => expression}/elementAccess.test.ts (65%) rename ts2panda/tests/{ => expression}/literal.test.ts (48%) create mode 100644 ts2panda/tests/expression/logicBinary.test.ts create mode 100644 ts2panda/tests/expression/operationEqual.test.ts create mode 100644 ts2panda/tests/expression/parenthesized.test.ts create mode 100644 ts2panda/tests/expression/postfixOperations.test.ts create mode 100644 ts2panda/tests/expression/prefixOperations.test.ts rename ts2panda/tests/{ => expression}/propertyAccess.test.ts (74%) create mode 100644 ts2panda/tests/expression/regular.test.js rename ts2panda/tests/expression/{TemplateExpression.test.ts => templateExpression.test.ts} (70%) rename ts2panda/tests/{otherExpressions.test.ts => expression/thisKeyWord.test.ts} (41%) create mode 100644 ts2panda/tests/expression/typeOf.test.ts create mode 100644 ts2panda/tests/expression/void.test.ts rename ts2panda/tests/{otherStatements.test.ts => statements/debugger.test.ts} (74%) create mode 100644 ts2panda/tests/statements/doWhile.test.ts rename ts2panda/tests/{loops.test.ts => statements/for.test.ts} (33%) create mode 100644 ts2panda/tests/statements/forOf.test.ts create mode 100644 ts2panda/tests/statements/functionDeclaration.test.ts rename ts2panda/tests/{returnStatement.test.ts => statements/return.test.ts} (68%) rename ts2panda/tests/{ => statements}/tryCatch.test.ts (78%) rename ts2panda/tests/{declaration.test.ts => statements/variableDeclaration.test.ts} (51%) create mode 100644 ts2panda/tests/statements/while.test.ts create mode 100644 ts2panda/tests/tsconfig.mac.json create mode 100644 ts2panda/tests/tsconfig.win.json delete mode 100644 ts2panda/tests/unary.test.ts diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 212e144a54..d01ca6cd5e 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -314,3 +314,52 @@ group("ark_ts2abc_build") { ] } } + +ohos_copy("ts2abc_tests") { + sources = [ "${ts2abc_root}/tests" ] + deps = [ ":npm_run_build" ] + + outputs = [ target_out_dir + "/tests" ] + module_install_name = "" +} + +group("ts2abc_unittests") { + deps = [ + "tests:arguments_tests(${buildtool_linux})", + "tests:binary_tests(${buildtool_linux})", + "tests:call_tests(${buildtool_linux})", + "tests:cmpBinary_tests(${buildtool_linux})", + "tests:conditions_tests(${buildtool_linux})", + "tests:debugger_tests(${buildtool_linux})", + "tests:delete_tests(${buildtool_linux})", + "tests:doWhile_tests(${buildtool_linux})", + "tests:elementAccess_tests(${buildtool_linux})", + "tests:forOf_tests(${buildtool_linux})", + "tests:for_tests(${buildtool_linux})", + "tests:forin_tests(${buildtool_linux})", + "tests:functionDeclaration_tests(${buildtool_linux})", + "tests:functionExpression_tests(${buildtool_linux})", + "tests:hello_tests(${buildtool_linux})", + "tests:literal_tests(${buildtool_linux})", + "tests:logicBinary_tests(${buildtool_linux})", + "tests:new_tests(${buildtool_linux})", + "tests:numericLiteral_tests(${buildtool_linux})", + "tests:operationEqual_tests(${buildtool_linux})", + "tests:parenthesized_tests(${buildtool_linux})", + "tests:postfixOperations_tests(${buildtool_linux})", + "tests:prefixOperations_tests(${buildtool_linux})", + "tests:propertyAccess_tests(${buildtool_linux})", + "tests:regular_tests(${buildtool_linux})", + "tests:return_tests(${buildtool_linux})", + "tests:strictmode_tests(${buildtool_linux})", + "tests:stringLiteral_tests(${buildtool_linux})", + "tests:switch_tests(${buildtool_linux})", + "tests:template_tests(${buildtool_linux})", + "tests:thisKeyWord_tests(${buildtool_linux})", + "tests:tryCatch_tests(${buildtool_linux})", + "tests:typeOf_tests(${buildtool_linux})", + "tests:variableDeclaration_tests(${buildtool_linux})", + "tests:void_tests(${buildtool_linux})", + "tests:while_tests(${buildtool_linux})", + ] +} diff --git a/ts2panda/scripts/run_tests.py b/ts2panda/scripts/run_tests.py new file mode 100755 index 0000000000..616f14f1e0 --- /dev/null +++ b/ts2panda/scripts/run_tests.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +""" +Copyright (c) 2021 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 os +import sys +import subprocess +import argparse +import time + +CUR_FILE_DIR = os.path.dirname(__file__) +TS2PANDA_DIR = os.path.abspath(os.path.join(CUR_FILE_DIR, "..")) +CODE_ROOT = os.path.abspath(os.path.join(TS2PANDA_DIR, "../../..")) +DEFAULT_TARGET_DIR = os.path.join( + CODE_ROOT, "out/ohos-arm-release/clang_x64/obj/ark/ts2abc/ts2panda") +DEFAULT_NODE_MODULE = os.path.join( + CODE_ROOT, "prebuilts/build-tools/common/ts2abc/node_modules") + + +def parse_args(): + parser = argparse.ArgumentParser() + + parser.add_argument('--src-dir', + default=TS2PANDA_DIR, + help='Source directory') + parser.add_argument('--dist-dir', + default=DEFAULT_TARGET_DIR, + help='Destination directory') + parser.add_argument("--node-modules", + default=DEFAULT_NODE_MODULE, + help='path to node-modules exetuable') + parser.add_argument('--platform', + default="linux", + help='platform, as: linux, mac, win') + parser.add_argument('--gn-build', + action='store_true', + help='Whether it is GN compilation') + parser.add_argument('--js-file', + metavar='FILE', + help='The name of the test use case file to execute') + + return parser.parse_args() + + +def run_command(cmd, execution_path=os.getcwd()): + print(" ".join(cmd)) + proc = subprocess.Popen(cmd, cwd=execution_path) + ret = proc.wait() + return ret + + +class Ts2abcTests(): + def __init__(self, args): + self.args = args + self.src_dir = TS2PANDA_DIR + self.dist_dir = DEFAULT_TARGET_DIR + self.node_modules = DEFAULT_NODE_MODULE + self.platform = "linux" + + def proce_parameters(self): + if self.args.src_dir: + self.src_dir = self.args.src_dir + + if self.args.dist_dir: + self.dist_dir = self.args.dist_dir + + if self.args.node_modules: + self.node_modules = self.args.node_modules + + if self.args.platform: + self.platform = self.args.platform + + def copy_node_modules(self): + src_dir = self.src_dir + dist_dir = self.dist_dir + run_command(['cp', '-f', os.path.join(src_dir, "package.json"), + os.path.join(dist_dir, "package.json")]) + run_command(['cp', '-f', os.path.join(src_dir, "package-lock.json"), + os.path.join(dist_dir, "package-lock.json")]) + + if self.node_modules: + run_command(['cp', '-rf', self.node_modules, dist_dir]) + else: + run_command(['npm', 'install'], dist_dir) + + def copy_tests(self): + if self.args.gn_build: + return + if os.path.exists(f'{self.dist_dir}/tests'): + run_command(['rm', '-rf', f'{self.dist_dir}/tests']) + run_command(['cp', '-rf', f'{self.src_dir}/tests', self.dist_dir]) + + def run_build(self): + plat_form = self.platform + tsc = "node_modules/typescript/bin/tsc" + if plat_form == "linux": + cmd = [tsc, '-b', 'src', 'tests'] + ret = run_command(cmd, self.dist_dir) + elif plat_form == "win": + cmd = [tsc, '-b', 'src/tsconfig.win.json', + 'tests/tsconfig.win.json'] + ret = run_command(cmd, self.dist_dir) + elif plat_form == 'mac': + cmd = [tsc, '-b', 'src/tsconfig.mac.json', + 'tests/tsconfig.mac.json'] + ret = run_command(cmd, self.dist_dir) + if ret : + raise RuntimeError("Run [" + " ".join(cmd) + "] failed !") + + def run_tests(self): + os.chdir(self.dist_dir) + start_time = time.time() + plat_form = self.platform + mocha = "node_modules/mocha/bin/mocha" + + if self.args.js_file: + tests_args = self.args.js_file + else: + tests_args = "**/*.test.js" + + if plat_form == "linux": + cmd = [mocha, f'build/tests/{tests_args}'] + ret = run_command(cmd, self.dist_dir) + elif plat_form == "win": + cmd = [mocha, f'build-win/tests/{tests_args}'] + ret = run_command(cmd, self.dist_dir) + elif plat_form == 'mac': + cmd = [mocha, f'build-mac/tests/{tests_args}'] + ret = run_command(cmd, self.dist_dir) + if ret: + raise RuntimeError("Run [" + " ".join(cmd) + "] failed !") + else: + print("Run [" + " ".join(cmd) + "] success!") + print("used: %.5f seconds" % (time.time() - start_time)) + + +def main(): + args = parse_args() + + test = Ts2abcTests(args) + test.copy_node_modules() + test.copy_tests() + test.run_build() + test.run_tests() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ts2panda/tests/BUILD.gn b/ts2panda/tests/BUILD.gn new file mode 100644 index 0000000000..0414b6f112 --- /dev/null +++ b/ts2panda/tests/BUILD.gn @@ -0,0 +1,163 @@ +# Copyright (c) 2021 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("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//build/config/clang/clang.gni") +import("//build/ohos.gni") + +# expression tests +ts2abc_unittest("binary_tests") { + js_file = "expression/binary.test.js" +} + +ts2abc_unittest("call_tests") { + js_file = "expression/call.test.js" +} + +ts2abc_unittest("conditions_tests") { + js_file = "expression/conditions.test.js" +} + +ts2abc_unittest("cmpBinary_tests") { + js_file = "expression/cmpBinary.test.js" +} + +ts2abc_unittest("delete_tests") { + js_file = "expression/delete.test.js" +} + +ts2abc_unittest("elementAccess_tests") { + js_file = "expression/elementAccess.test.js" +} + +ts2abc_unittest("functionExpression_tests") { + js_file = "expression/functionExpression.test.js" +} + +ts2abc_unittest("literal_tests") { + js_file = "expression/literal.test.js" +} + +ts2abc_unittest("logicBinary_tests") { + js_file = "expression/logicBinary.test.js" +} + +ts2abc_unittest("new_tests") { + js_file = "expression/new.test.js" +} + +ts2abc_unittest("numericLiteral_tests") { + js_file = "expression/numericLiteral.test.js" +} + +ts2abc_unittest("operationEqual_tests") { + js_file = "expression/operationEqual.test.js" +} + +ts2abc_unittest("parenthesized_tests") { + js_file = "expression/parenthesized.test.js" +} + +ts2abc_unittest("arguments_tests") { + js_file = "expression/arguments.test.js" +} + +ts2abc_unittest("propertyAccess_tests") { + js_file = "expression/propertyAccess.test.js" +} + +ts2abc_unittest("postfixOperations_tests") { + js_file = "expression/postfixOperations.test.js" +} + +ts2abc_unittest("stringLiteral_tests") { + js_file = "expression/stringLiteral.test.js" +} + +ts2abc_unittest("template_tests") { + js_file = "expression/templateExpression.test.js" +} + +ts2abc_unittest("thisKeyWord_tests") { + js_file = "expression/thisKeyWord.test.js" +} + +ts2abc_unittest("typeOf_tests") { + js_file = "expression/typeOf.test.js" +} + +ts2abc_unittest("void_tests") { + js_file = "expression/void.test.js" +} + +ts2abc_unittest("prefixOperations_tests") { + js_file = "expression/prefixOperations.test.js" +} + +ts2abc_unittest("regular_tests") { + js_file = "expression/regular.test.js" +} + +# ststement tests +ts2abc_unittest("debugger_tests") { + js_file = "statements/debugger.test.js" +} + +ts2abc_unittest("functionDeclaration_tests") { + js_file = "statements/functionDeclaration.test.js" +} + +ts2abc_unittest("doWhile_tests") { + js_file = "statements/doWhile.test.js" +} + +ts2abc_unittest("for_tests") { + js_file = "statements/for.test.js" +} + +ts2abc_unittest("forin_tests") { + js_file = "statements/forIn.test.js" +} + +ts2abc_unittest("forOf_tests") { + js_file = "statements/forOf.test.js" +} + +ts2abc_unittest("return_tests") { + js_file = "statements/return.test.js" +} + +ts2abc_unittest("switch_tests") { + js_file = "statements/switch.test.js" +} + +ts2abc_unittest("tryCatch_tests") { + js_file = "statements/tryCatch.test.js" +} + +ts2abc_unittest("variableDeclaration_tests") { + js_file = "statements/variableDeclaration.test.js" +} + +ts2abc_unittest("while_tests") { + js_file = "statements/while.test.js" +} + +# other tests +ts2abc_unittest("strictmode_tests") { + js_file = "strictmode/strictmode.test.js" +} + +ts2abc_unittest("hello_tests") { + js_file = "example_hello/hello.test.js" +} diff --git a/ts2panda/tests/builtIns.test.ts b/ts2panda/tests/builtIns.test.ts index ced5796134..2484fba12f 100644 --- a/ts2panda/tests/builtIns.test.ts +++ b/ts2panda/tests/builtIns.test.ts @@ -18,21 +18,21 @@ import { } from 'chai'; import 'mocha'; import { + EcmaReturnundefined, LdaDyn, - ReturnUndefined, VReg } from "../src/irnodes"; import { checkInstructions, compileMainSnippet } from "./utils/base"; -describe("BuiltInsTest", function() { - it("Global Value Properties", function() { +describe("BuiltInsTest", function () { + it("Global Value Properties", function () { let insns = compileMainSnippet(`NaN; Infinity; globalThis;`); let expected = [ new LdaDyn(new VReg()), new LdaDyn(new VReg()), new LdaDyn(new VReg()), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/expression/arguments.test.ts b/ts2panda/tests/expression/arguments.test.ts new file mode 100644 index 0000000000..660e1b72b0 --- /dev/null +++ b/ts2panda/tests/expression/arguments.test.ts @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaGetunmappedargs, + EcmaLdobjbyindex, + EcmaReturnundefined, + Imm, + LdaDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, SnippetCompiler } from "../utils/base"; + +describe("arguments Keyword", function () { + it('arguments: Array-like object accessible inside functions', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`function foo(a,b) {arguments[0];}`); + let argumentsReg = new VReg(); + let temp1 = new VReg(); + let expected = [ + new EcmaGetunmappedargs(), + new StaDyn(argumentsReg), + new LdaDyn(argumentsReg), + new StaDyn(temp1), + new EcmaLdobjbyindex(temp1, new Imm(ResultType.Int, 0)), + new EcmaReturnundefined() + ]; + let functionPg = snippetCompiler.getPandaGenByName("foo"); + let insns = functionPg!.getInsns(); + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('arguments as parameter shadows keyword', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`function foo(arguments) {arguments[0];}`); + let parameterArguments = new VReg(); + let temp1 = new VReg(); + let expected = [ + new EcmaGetunmappedargs(), + new StaDyn(new VReg()), + new LdaDyn(parameterArguments), + new StaDyn(temp1), + new EcmaLdobjbyindex(temp1, new Imm(ResultType.Int, 0)), + new EcmaReturnundefined() + ]; + let functionPg = snippetCompiler.getPandaGenByName("foo"); + let insns = functionPg!.getInsns(); + + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); diff --git a/ts2panda/tests/binary.test.ts b/ts2panda/tests/expression/binary.test.ts similarity index 31% rename from ts2panda/tests/binary.test.ts rename to ts2panda/tests/expression/binary.test.ts index 3f996596b1..f80ba94f38 100644 --- a/ts2panda/tests/binary.test.ts +++ b/ts2panda/tests/expression/binary.test.ts @@ -18,79 +18,68 @@ import { } from 'chai'; import 'mocha'; import { - Add2Dyn, - And2Dyn, - Ashr2Dyn, - CreateEmptyObject, - Div2Dyn, - EqDyn, - ExpDyn, - GreaterDyn, - GreaterEqDyn, + EcmaAdd2dyn, + EcmaAnd2dyn, + EcmaAshr2dyn, + EcmaCreateemptyobject, + EcmaDiv2dyn, + EcmaExpdyn, + EcmaMod2dyn, + EcmaMul2dyn, + EcmaOr2dyn, + EcmaReturnundefined, + EcmaShl2dyn, + EcmaShr2dyn, + EcmaStglobalvar, + EcmaStlettoglobalrecord, + EcmaStobjbyname, + EcmaStrictnoteqdyn, + EcmaSub2dyn, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + EcmaXor2dyn, Imm, - IncDyn, - InstanceOfDyn, - IsInDyn, Jeqz, Jmp, Label, LdaDyn, LdaiDyn, LdaStr, - LessDyn, - LessEqDyn, - Mod2Dyn, MovDyn, - Mul2Dyn, - NotEqDyn, - Or2Dyn, ResultType, - ReturnUndefined, - Shl2Dyn, - Shr2Dyn, StaDyn, - StGlobalVar, - StObjByName, - StrictEqDyn, - StrictNotEqDyn, - Sub2Dyn, - Toboolean, - Tonumber, - TryLdGlobalByName, - TryStGlobalByName, - VReg, - Xor2Dyn -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; - -describe("BinaryOperationsTest", function() { - it("2 + 3", function() { + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("BinaryOperationsTest", function () { + it("2 + 3", function () { let insns = compileMainSnippet("2 + 3"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 3)), - new Add2Dyn(lhs), - new ReturnUndefined() + new EcmaAdd2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("5 - 1", function() { + it("5 - 1", function () { let insns = compileMainSnippet("5 - 1"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 5)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 1)), - new Sub2Dyn(lhs), - new ReturnUndefined() + new EcmaSub2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("null ?? 1", function() { + it("null ?? 1", function () { let insns = compileMainSnippet("null ?? 1"); let leftNullishLabel = new Label(); @@ -98,17 +87,17 @@ describe("BinaryOperationsTest", function() { let expected = [ new LdaDyn(new VReg()), new StaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(new VReg()), new Jmp(endLabel), leftNullishLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), endLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -118,7 +107,7 @@ describe("BinaryOperationsTest", function() { expect(jumps.length).to.equal(3); }); - it("undefined ?? 1", function() { + it("undefined ?? 1", function () { let insns = compileMainSnippet("undefined ?? 1"); let leftNullishLabel = new Label(); @@ -126,10 +115,10 @@ describe("BinaryOperationsTest", function() { let expected = [ new LdaDyn(new VReg()), new StaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(new VReg()), @@ -138,7 +127,7 @@ describe("BinaryOperationsTest", function() { leftNullishLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), endLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -147,7 +136,7 @@ describe("BinaryOperationsTest", function() { expect(jumps.length).to.equal(3); }); - it("2 ?? 1", function() { + it("2 ?? 1", function () { let insns = compileMainSnippet("2 ?? 1"); let lhs = new VReg(); @@ -156,10 +145,10 @@ describe("BinaryOperationsTest", function() { let expected = [ new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(new VReg()), - new StrictNotEqDyn(new VReg()), + new EcmaStrictnoteqdyn(new VReg()), new Jeqz(leftNullishLabel), new LdaDyn(lhs), @@ -168,7 +157,7 @@ describe("BinaryOperationsTest", function() { leftNullishLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), endLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -177,150 +166,149 @@ describe("BinaryOperationsTest", function() { expect(jumps.length).to.equal(3); }); - it("3 * 4", function() { + it("3 * 4", function () { let insns = compileMainSnippet("3 * 4"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 3)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 4)), - new Mul2Dyn(lhs), - new ReturnUndefined() + new EcmaMul2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("2 ** 3", function() { + it("2 ** 3", function () { let insns = compileMainSnippet("2 ** 3"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 3)), - new ExpDyn(lhs), - new ReturnUndefined(), + new EcmaExpdyn(lhs), + new EcmaReturnundefined(), ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("7 / 1", function() { + it("7 / 1", function () { let insns = compileMainSnippet("7 / 1"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 7)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 1)), - new Div2Dyn(lhs), - new ReturnUndefined() + new EcmaDiv2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("8 % 2", function() { + it("8 % 2", function () { let insns = compileMainSnippet("8 % 2"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 8)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 2)), - new Mod2Dyn(lhs), - new ReturnUndefined() + new EcmaMod2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("2 << 3", function() { + it("2 << 3", function () { let insns = compileMainSnippet("2 << 3"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 3)), - new Shl2Dyn(lhs), - new ReturnUndefined() + new EcmaShl2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("4 >> 1", function() { + it("4 >> 1", function () { let insns = compileMainSnippet("4 >> 1"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 4)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 1)), - new Shr2Dyn(lhs), - new ReturnUndefined() + new EcmaShr2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("12 >>> 2", function() { + it("12 >>> 2", function () { let insns = compileMainSnippet("12 >>> 2"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 12)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 2)), - new Ashr2Dyn(lhs), - new ReturnUndefined() + new EcmaAshr2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("3 & 4", function() { + it("3 & 4", function () { let insns = compileMainSnippet("3 & 4"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 3)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 4)), - new And2Dyn(lhs), - new ReturnUndefined() + new EcmaAnd2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("2 | 5", function() { + it("2 | 5", function () { let insns = compileMainSnippet("2 | 5"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 5)), - new Or2Dyn(lhs), - new ReturnUndefined() + new EcmaOr2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("7 ^ 3", function() { + it("7 ^ 3", function () { let insns = compileMainSnippet("7 ^ 3"); let lhs = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 7)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 3)), - new Xor2Dyn(lhs), - new ReturnUndefined() + new EcmaXor2dyn(lhs), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let i; i = 2", function() { + it("let i; i = 2", function () { let insns = compileMainSnippet("let i; i = 2;"); - let i = new VReg(); let expected = [ new LdaDyn(new VReg()), - new StaDyn(i), + new EcmaStlettoglobalrecord('i'), new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(i), - new ReturnUndefined() + new EcmaTrystglobalbyname('i'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("a = 1 under strict mode", function() { + it("a = 1 under strict mode", function () { let insns = compileMainSnippet(` "use strict"; a = 1; @@ -328,552 +316,44 @@ describe("BinaryOperationsTest", function() { let expected = [ new LdaStr("use strict"), new LdaiDyn(new Imm(ResultType.Int, 1)), - new TryStGlobalByName("a"), - new ReturnUndefined() + new EcmaTrystglobalbyname("a"), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }) - it("Assignment to ParenthesizedExpression case1", function() { + it("Assignment to ParenthesizedExpression case1", function () { let insns = compileMainSnippet("((x)) = 1;"); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 1)), - new StGlobalVar("x"), - new ReturnUndefined() + new EcmaStglobalvar("x"), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("Assignment to ParenthesizedExpression case2", function() { + it("Assignment to ParenthesizedExpression case2", function () { let insns = compileMainSnippet(`let a = {}; ((a.b)) = 1;`); let objReg = new VReg(); let tempObj = new VReg(); let expected = [ - new CreateEmptyObject(), + new EcmaCreateemptyobject(), new StaDyn(new VReg()), - new StaDyn(objReg), // insns for `((a.b)) = 1` - new LdaDyn(objReg), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), new StaDyn(tempObj), new MovDyn(objReg, tempObj), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StObjByName("b", objReg), - new ReturnUndefined() - ] - expect(checkInstructions(insns, expected)).to.be.true; - }); -}); - -describe("OperationEqualTest", function() { - it("plusEqual", function() { - let insns = compileMainSnippet("let a = 2;\n" + - "a += 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new Add2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("minusEqual", function() { - let insns = compileMainSnippet("let a = 5;\n" + - "a -= 7;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 7)), - new Sub2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("asteriskEqual", function() { - let insns = compileMainSnippet("let a = 2;\n" + - "a *= 4;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 4)), - new Mul2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("AsteriskAsteriskEqualsToken", function() { - let insns = compileMainSnippet("let a = 2;\n" + - "a **= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new ExpDyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ] - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("slashEqual", function() { - let insns = compileMainSnippet("let a = 5;\n" + - "a /= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new Div2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("percentEqual", function() { - let insns = compileMainSnippet("let a = 15;\n" + - "a %= 7;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 15)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 7)), - new Mod2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("lessThanLessThanEqual", function() { - let insns = compileMainSnippet("let a = 8;\n" + - "a <<= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 8)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new Shl2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("greaterThanGreaterThanEqual", function() { - let insns = compileMainSnippet("let a = 4;\n" + - "a >>= 1;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 4)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new Shr2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("greaterThanGreaterThanGreaterThanEqual", function() { - let insns = compileMainSnippet("let a = 8;\n" + - "a >>>= 2;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 8)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 2)), - new Ashr2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); -}); - -describe("LogicBinaryOperators", function() { - it("ampersandAmpersand", function() { - let insns = compileMainSnippet("8 && false;"); - let lhs = new VReg(); - let preLabel = new Label(); - let postLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 8)), - new StaDyn(lhs), - new Toboolean(), - new EqDyn(new VReg()), - new Jeqz(preLabel), - new LdaDyn(new VReg()), - new Jmp(postLabel), - preLabel, - new LdaDyn(lhs), - postLabel, - new ReturnUndefined() - ] - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("barBar", function() { - let insns = compileMainSnippet("8 || false;"); - let lhs = new VReg(); - let rhs = new VReg(); - let preLabel = new Label(); - let postLabel = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 8)), - new StaDyn(lhs), - new Toboolean(), - new EqDyn(rhs), - new Jeqz(preLabel), - new LdaDyn(new VReg()), - new Jmp(postLabel), - preLabel, - new LdaDyn(lhs), - postLabel, - new ReturnUndefined() + new EcmaStobjbyname("b", objReg), + new EcmaReturnundefined() ] - - expect(checkInstructions(insns, expected)).to.be.true; - }); -}); - -describe("CmpBinaryOperators", function() { - it("LessThan", function() { - let insns = compileMainSnippet("2 < 3;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new LessDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("GreaterThan", function() { - let insns = compileMainSnippet("3 > 1;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new GreaterDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("LessThanEquals", function() { - let insns = compileMainSnippet("3 <= 4;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 4)), - new LessEqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("GreaterThanEquals", function() { - let insns = compileMainSnippet("3 >= 2;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 2)), - new GreaterEqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("EqualsEquals", function() { - let insns = compileMainSnippet("3 == 3;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new EqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("ExclamationEquals", function() { - let insns = compileMainSnippet("3 != 2;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 2)), - new NotEqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("EqualsEqualsEquals", function() { - let insns = compileMainSnippet("3 === 3;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StrictEqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("ExclamationEqualsEquals", function() { - let insns = compileMainSnippet("3 !== 3;"); - let lhs = new VReg(); - let falseLabel = new Label(); - let endLabel = new Label(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new StrictNotEqDyn(lhs), - new Jeqz(falseLabel), - new LdaDyn(new VReg()), - new Jmp(endLabel), - falseLabel, - new LdaDyn(new VReg()), - endLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("ampersandEqual", function() { - let insns = compileMainSnippet("let a = 5;\n" + - "a &= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new And2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("barEqual", function() { - let insns = compileMainSnippet("let a = 5;\n" + - "a |= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new Or2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("caretEqual", function() { - let insns = compileMainSnippet("let a = 5;\n" + - "a ^= 3;"); - let a = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 3)), - new Xor2Dyn(lhs), - new StaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("CommaToken", function() { - let insns = compileMainSnippet(`let x = 1; - x = (x++, x);`); - let variable = new VReg(); - let rhs = new VReg(); - let lhs = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(variable), - new LdaDyn(variable), - new StaDyn(lhs), - new IncDyn(lhs), - new StaDyn(variable), - new Tonumber(variable), - new StaDyn(rhs), - new LdaDyn(variable), - new StaDyn(variable), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("InKeyword", function() { - let insns = compileMainSnippet(`'o' in C;`); - let rhs = new VReg(); - - let expected = [ - new LdaStr('o'), - new StaDyn(rhs), - new TryLdGlobalByName("C"), - new IsInDyn(rhs), - new ReturnUndefined() - ]; expect(checkInstructions(insns, expected)).to.be.true; }); - - it("InstanceOfKeyword", function() { - let insns = compileMainSnippet(`o instanceof C;`); - let rhs = new VReg(); - - let expected = [ - new TryLdGlobalByName("o"), - new StaDyn(rhs), - new TryLdGlobalByName("C"), - new InstanceOfDyn(rhs), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); diff --git a/ts2panda/tests/expression/call.test.ts b/ts2panda/tests/expression/call.test.ts index 95a2fbb7d5..c19a8a45ac 100755 --- a/ts2panda/tests/expression/call.test.ts +++ b/ts2panda/tests/expression/call.test.ts @@ -18,65 +18,65 @@ import { } from 'chai'; import 'mocha'; import { - Call0Dyn, - Call1Dyn, - CalliThisRangeDyn, - CallSpread, - CreateArrayWithBuffer, - CreateEmptyArray, + EcmaCallarg0dyn, + EcmaCallarg1dyn, + EcmaCallithisrangedyn, + EcmaCallspreaddyn, + EcmaCreatearraywithbuffer, + EcmaCreateemptyarray, + EcmaLdobjbyname, + EcmaLdobjbyvalue, + EcmaReturnundefined, + EcmaStarrayspread, + EcmaStconsttoglobalrecord, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, Imm, LdaDyn, LdaiDyn, - LdObjByName, - LdObjByValue, ResultType, - ReturnUndefined, StaDyn, - StArraySpread, - TryLdGlobalByName, VReg } from "../../src/irnodes"; import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("CallTest", function() { - it("no arg call of a global standalone function", function() { +describe("CallTest", function () { + it("no arg call of a global standalone function", function () { let insns = compileMainSnippet(` foo(); `); let arg0 = new VReg(); let expected = [ - new TryLdGlobalByName("foo"), + new EcmaTryldglobalbyname("foo"), new StaDyn(arg0), - new Call0Dyn(arg0), + new EcmaCallarg0dyn(arg0), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("one arg call of a global standalone function", function() { + it("one arg call of a global standalone function", function () { let insns = compileMainSnippet(` let i = 5; foo(i); `); - let i = new VReg(); let arg0 = new VReg(); let arg2 = new VReg(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new TryLdGlobalByName("foo"), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname("foo"), new StaDyn(arg0), - new LdaDyn(i), + new EcmaTryldglobalbyname('i'), new StaDyn(arg2), - new Call1Dyn(arg0, arg2), - - new ReturnUndefined() + new EcmaCallarg1dyn(arg0, arg2), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("call method", function() { + it("call method", function () { let insns = compileMainSnippet(` Foo.method(); `); @@ -84,18 +84,18 @@ describe("CallTest", function() { let arg0 = new VReg(); let arg1 = new VReg(); let expected = [ - new TryLdGlobalByName("Foo"), + new EcmaTryldglobalbyname("Foo"), new StaDyn(arg0), - new LdObjByName("method", arg0), + new EcmaLdobjbyname("method", arg0), new StaDyn(arg1), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [arg1, obj]), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [arg1, obj]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("spread element call of a global standalone function", function() { + it("spread element call of a global standalone function", function () { let insns = compileMainSnippet(` const args = [1, 2]; myFunction(...args); @@ -104,34 +104,32 @@ describe("CallTest", function() { let globalEnv = new VReg(); let lengthReg = new VReg(); let arrayInstance = new VReg(); - let objReg = new VReg(); let expected = [ - new CreateArrayWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(arrayInstance), new LdaDyn(arrayInstance), - new StaDyn(objReg), + new EcmaStconsttoglobalrecord('args'), - new TryLdGlobalByName("myFunction"), + new EcmaTryldglobalbyname("myFunction"), new StaDyn(arg0), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(arrayInstance), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(lengthReg), - new LdaDyn(objReg), - new StArraySpread(arrayInstance, lengthReg), + new EcmaTryldglobalbyname('args'), + new EcmaStarrayspread(arrayInstance, lengthReg), new StaDyn(lengthReg), new LdaDyn(arrayInstance), - new CallSpread(arg0, globalEnv, arrayInstance), - - new ReturnUndefined() + new EcmaCallspreaddyn(arg0, globalEnv, arrayInstance), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("call by element access", function() { + it("call by element access", function () { let insns = compileMainSnippet(` Foo[method](); `); @@ -140,15 +138,15 @@ describe("CallTest", function() { let arg0 = new VReg(); let arg1 = new VReg(); let expected = [ - new TryLdGlobalByName("Foo"), + new EcmaTryldglobalbyname("Foo"), new StaDyn(arg0), - new TryLdGlobalByName("method"), + new EcmaTryldglobalbyname("method"), new StaDyn(prop), - new LdObjByValue(arg0, prop), + new EcmaLdobjbyvalue(arg0, prop), new StaDyn(arg1), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [arg1, obj]), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [arg1, obj]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/expression/cmpBinary.test.ts b/ts2panda/tests/expression/cmpBinary.test.ts new file mode 100644 index 0000000000..2534c932ac --- /dev/null +++ b/ts2panda/tests/expression/cmpBinary.test.ts @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaAnd2dyn, + EcmaEqdyn, + EcmaGreaterdyn, + EcmaGreatereqdyn, + EcmaIncdyn, + EcmaInstanceofdyn, + EcmaIsindyn, + EcmaLessdyn, + EcmaLesseqdyn, + EcmaNoteqdyn, + EcmaOr2dyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaStricteqdyn, + EcmaStrictnoteqdyn, + EcmaTonumber, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + EcmaXor2dyn, + Imm, + Jeqz, + Jmp, + Label, + LdaDyn, + LdaiDyn, + LdaStr, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("CmpBinaryOperators", function () { + it("LessThan", function () { + let insns = compileMainSnippet("2 < 3;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 2)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaLessdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("GreaterThan", function () { + let insns = compileMainSnippet("3 > 1;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaGreaterdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("LessThanEquals", function () { + let insns = compileMainSnippet("3 <= 4;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 4)), + new EcmaLesseqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("GreaterThanEquals", function () { + let insns = compileMainSnippet("3 >= 2;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaGreatereqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("EqualsEquals", function () { + let insns = compileMainSnippet("3 == 3;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaEqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("ExclamationEquals", function () { + let insns = compileMainSnippet("3 != 2;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaNoteqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("EqualsEqualsEquals", function () { + let insns = compileMainSnippet("3 === 3;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaStricteqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("ExclamationEqualsEquals", function () { + let insns = compileMainSnippet("3 !== 3;"); + let lhs = new VReg(); + let falseLabel = new Label(); + let endLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 3)), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaStrictnoteqdyn(lhs), + new Jeqz(falseLabel), + new LdaDyn(new VReg()), + new Jmp(endLabel), + falseLabel, + new LdaDyn(new VReg()), + endLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("ampersandEqual", function () { + let insns = compileMainSnippet("let a = 5;\n" + + "a &= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaAnd2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("barEqual", function () { + let insns = compileMainSnippet("let a = 5;\n" + + "a |= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaOr2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("caretEqual", function () { + let insns = compileMainSnippet("let a = 5;\n" + + "a ^= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaXor2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("CommaToken", function () { + let insns = compileMainSnippet(`let x = 1; + x = (x++, x);`); + let variable = new VReg(); + let rhs = new VReg(); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaStlettoglobalrecord('x'), + new EcmaTryldglobalbyname('x'), + new StaDyn(lhs), + new EcmaIncdyn(lhs), + new EcmaTrystglobalbyname('x'), + new EcmaTonumber(variable), + new StaDyn(rhs), + new EcmaTryldglobalbyname('x'), + new EcmaTrystglobalbyname('x'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("InKeyword", function () { + let insns = compileMainSnippet(`'o' in C;`); + let rhs = new VReg(); + + let expected = [ + new LdaStr('o'), + new StaDyn(rhs), + new EcmaTryldglobalbyname("C"), + new EcmaIsindyn(rhs), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("InstanceOfKeyword", function () { + let insns = compileMainSnippet(`o instanceof C;`); + let rhs = new VReg(); + + let expected = [ + new EcmaTryldglobalbyname("o"), + new StaDyn(rhs), + new EcmaTryldglobalbyname("C"), + new EcmaInstanceofdyn(rhs), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + +}); diff --git a/ts2panda/tests/conditions.test.ts b/ts2panda/tests/expression/conditions.test.ts similarity index 76% rename from ts2panda/tests/conditions.test.ts rename to ts2panda/tests/expression/conditions.test.ts index ae7b88840e..8e15bd616b 100644 --- a/ts2panda/tests/conditions.test.ts +++ b/ts2panda/tests/expression/conditions.test.ts @@ -18,8 +18,13 @@ import { } from 'chai'; import 'mocha'; import { - And2Dyn, - EqDyn, + EcmaAnd2dyn, + EcmaEqdyn, + EcmaIsfalse, + EcmaIstrue, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, Imm, Jeqz, Jlez, @@ -27,18 +32,14 @@ import { Label, LdaDyn, LdaiDyn, - NotEqDyn, ResultType, - ReturnDyn, StaDyn, - VReg, - Toboolean, - ReturnUndefined, -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; - -describe("IfConditionTest", function() { - it('ifConditionEmpty', function() { + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("IfConditionTest", function () { + it('ifConditionEmpty', function () { let insns = compileMainSnippet("let s = 1;\n" + "if (s > 2) {}"); let jumps = insns.filter(item => item instanceof Jeqz); @@ -50,7 +51,7 @@ describe("IfConditionTest", function() { expect(targetLabel).to.equal(insns[insns.length - 2]); }); - it('ifConditionWithThenStatement', function() { + it('ifConditionWithThenStatement', function () { let insns = compileMainSnippet("let a = 2;\n" + "if (a > 4) {\n" + " a = 3;\n" + @@ -64,7 +65,7 @@ describe("IfConditionTest", function() { expect(targetLabel).to.equal(insns[insns.length - 2]); }); - it('ifConditionWithThenStatementAndElseStatement', function() { + it('ifConditionWithThenStatementAndElseStatement', function () { let insns = compileMainSnippet("let a = 5;\n" + "if (a > 3) {\n" + " a = 2;\n" + @@ -87,25 +88,21 @@ describe("IfConditionTest", function() { expect(endIfLabel).to.equal(insns[insns.length - 2]); }); - it("if (a & b)", function() { + it("if (a & b)", function () { let insns = compileMainSnippet(` let a = 1; let b = 2; if (a & b) { } `); - let a = new VReg(); - let b = new VReg(); let lhs = new VReg(); - let trueReg = new VReg(); let endIfLabel = new Label(); let expected = [ - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(lhs), - new LdaDyn(b), - new And2Dyn(lhs), - new Toboolean(), - new EqDyn(trueReg), + new EcmaTryldglobalbyname('b'), + new EcmaAnd2dyn(lhs), + new EcmaIstrue(), new Jeqz(endIfLabel), endIfLabel, ]; @@ -113,22 +110,21 @@ describe("IfConditionTest", function() { expect(checkInstructions(insns, expected)).to.be.true }); - it("if (a = b)", function() { + it("if (a == b)", function () { let insns = compileMainSnippet(` let a = 1; let b = 2; - if (a = b) { + if (a == b) { } `); let a = new VReg(); - let b = new VReg(); let trueReg = new VReg(); let endIfLabel = new Label(); let expected = [ - new LdaDyn(b), + new EcmaTryldglobalbyname('a'), new StaDyn(a), - new Toboolean(), - new EqDyn(trueReg), + new EcmaTryldglobalbyname('b'), + new EcmaEqdyn(trueReg), new Jeqz(endIfLabel), endIfLabel, ]; @@ -136,25 +132,22 @@ describe("IfConditionTest", function() { expect(checkInstructions(insns, expected)).to.be.true; }); - it("let a = true ? 5 : 0;", function() { + it("let a = true ? 5 : 0;", function () { let insns = compileMainSnippet(`let a = true ? 5 : 0;`); insns = insns.slice(0, insns.length - 1); - let trueReg = new VReg(); - let tempReg = new VReg(); let expectedElseLabel = new Label(); let expectedEndLabel = new Label(); let expected = [ new LdaDyn(new VReg()), - new Toboolean(), - new EqDyn(trueReg), + new EcmaIstrue(), new Jeqz(expectedElseLabel), new LdaiDyn(new Imm(ResultType.Int, 5)), new Jmp(expectedEndLabel), expectedElseLabel, new LdaiDyn(new Imm(ResultType.Int, 0)), expectedEndLabel, - new StaDyn(tempReg) + new EcmaStlettoglobalrecord('a'), ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -165,42 +158,36 @@ describe("IfConditionTest", function() { expect(labels.length).to.equal(2); }); - it("if (true && 5) {}", function() { + it("if (true && 5) {}", function () { let insns = compileMainSnippet("if (true && 5) {}"); - let trueReg = new VReg(); let ifFalseLabel = new Label(); let expected = [ new LdaDyn(new VReg()), - new Toboolean(), - new EqDyn(trueReg), + new EcmaIstrue(), new Jeqz(ifFalseLabel), new LdaiDyn(new Imm(ResultType.Int, 5)), - new Toboolean(), - new EqDyn(trueReg), + new EcmaIstrue(), new Jeqz(ifFalseLabel), ifFalseLabel, - new ReturnUndefined() + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); - it("if (false || 5) {}", function() { + it("if (false || 5) {}", function () { let insns = compileMainSnippet("if (false || 5) {}"); - let falseReg = new VReg(); let ifFalseLabel = new Label(); let endLabel = new Label(); let expected = [ new LdaDyn(new VReg()), - new Toboolean(), - new EqDyn(falseReg), + new EcmaIsfalse(), new Jeqz(endLabel), new LdaiDyn(new Imm(ResultType.Int, 5)), - new Toboolean(), - new NotEqDyn(falseReg), + new EcmaIstrue(), new Jeqz(ifFalseLabel), endLabel, ifFalseLabel, - new ReturnUndefined() + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/expression/delete.test.ts b/ts2panda/tests/expression/delete.test.ts new file mode 100644 index 0000000000..8c7f3a1ace --- /dev/null +++ b/ts2panda/tests/expression/delete.test.ts @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaDelobjprop, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, + Imm, + LdaDyn, + LdaiDyn, + LdaStr, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet, SnippetCompiler } from "../utils/base"; + +describe("deleteExpressionTest", function () { + it("deleteElementFromArray", function () { + let insns = compileMainSnippet("let arr = [1, 2]; delete arr[1];"); + + let objReg = new VReg(); + let propReg = new VReg(); + + let expected = [ + // let arr = [1, 2]; + // ... + // delete arr[1]; + new EcmaStlettoglobalrecord('arr'), + new EcmaTryldglobalbyname('arr'), + new StaDyn(objReg), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new StaDyn(propReg), + new EcmaDelobjprop(objReg, propReg), + new EcmaReturnundefined() + ]; + + insns = insns.slice(insns.length - 7, insns.length); + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("deletePropFromObj", function () { + // this Snippet code isn't supported by TS + let insns = compileMainSnippet(`let obj = { + a: 1, + b: 2}; + delete obj.b;`); + let objReg = new VReg(); + let propReg = new VReg(); + + let expected = [ + // delete obj.b; + new EcmaStlettoglobalrecord('obj'), + new EcmaTryldglobalbyname('obj'), + new StaDyn(objReg), + new LdaStr("b"), + new StaDyn(propReg), + new EcmaDelobjprop(objReg, propReg), + new EcmaReturnundefined() + ]; + + insns = insns.slice(insns.length - 7, insns.length); + expect(checkInstructions(insns, expected)).to.be.true; + }); + + // delete function call won't use delObjProp + it("deleteFunctionCall", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`var foo = function() { + bIsFooCalled = true; + }; + let a = delete foo();`); + + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + // function call insns + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('a'), + new EcmaReturnundefined() + ]; + + insns = insns.slice(insns.length - 3, insns.length); + expect(checkInstructions(insns, expected)).to.be.true; + }); + + // delete keywords won't use delObjProp + it("deleteKeywords", function () { + let insns = compileMainSnippet(`let a = delete false;`); + + let expected = [ + new LdaDyn(new VReg()), + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('a'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("deleteUnresolvable", function () { + let insns = compileMainSnippet(`delete a;`); + let globalReg = new VReg(); + let a = new VReg(); + + let expected = [ + new LdaStr("a"), + new StaDyn(a), + new EcmaDelobjprop(globalReg, a), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("double delete", function () { + let insns = compileMainSnippet(`delete delete a;`); + let globalReg = new VReg(); + let a = new VReg(); + + let expected = [ + new LdaStr("a"), + new StaDyn(a), + new EcmaDelobjprop(globalReg, a), + new LdaDyn(new VReg()), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/elementAccess.test.ts b/ts2panda/tests/expression/elementAccess.test.ts similarity index 65% rename from ts2panda/tests/elementAccess.test.ts rename to ts2panda/tests/expression/elementAccess.test.ts index 8f8b26ebe3..3a466cfd11 100644 --- a/ts2panda/tests/elementAccess.test.ts +++ b/ts2panda/tests/expression/elementAccess.test.ts @@ -18,56 +18,59 @@ import { } from 'chai'; import 'mocha'; import { - Add2Dyn, + EcmaAdd2dyn, + EcmaLdobjbyname, + EcmaLdobjbyvalue, + EcmaStlettoglobalrecord, + EcmaStobjbyname, + EcmaTryldglobalbyname, Imm, - LdaDyn, LdaiDyn, - LdObjByName, - LdObjByValue, MovDyn, ResultType, StaDyn, - StObjByName, VReg -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("ElementAccess", function() { - it('get obj["property"]', function() { +describe("ElementAccess", function () { + it('get obj["property"]', function () { let insns = compileMainSnippet(`let obj; obj["property"];`); let objReg = new VReg(); let expected = [ - new LdaDyn(objReg), + new EcmaStlettoglobalrecord('obj'), + new EcmaTryldglobalbyname('obj'), new StaDyn(objReg), - new LdObjByName("property", objReg) + new EcmaLdobjbyname("property", objReg), ]; - insns = insns.slice(2, insns.length - 1); // cut off let obj and return.dyn + insns = insns.slice(1, insns.length - 1); // cut off let obj and return.dyn expect(checkInstructions(insns, expected)).to.be.true; }); - it('set obj["property"]', function() { + it('set obj["property"]', function () { let insns = compileMainSnippet(`let obj; obj["property"] = 5;`); let objReg = new VReg(); let tempObj = new VReg(); let expected = [ - new LdaDyn(objReg), + new EcmaStlettoglobalrecord('obj'), + new EcmaTryldglobalbyname('obj'), new StaDyn(tempObj), new MovDyn(objReg, tempObj), new LdaiDyn(new Imm(ResultType.Int, 5)), - new StObjByName("property", objReg), + new EcmaStobjbyname("property", objReg), ]; - insns = insns.slice(2, insns.length - 1); // cut off let obj and return.dyn + insns = insns.slice(1, insns.length - 1); // cut off let obj and return.dyn expect(checkInstructions(insns, expected)).to.be.true; }); - it('get obj[1 + 2]', function() { + it('get obj[1 + 2]', function () { let insns = compileMainSnippet(`let obj; obj[1 + 2];`); let prop1Reg = new VReg(); @@ -75,17 +78,17 @@ describe("ElementAccess", function() { let val = new VReg(); let expected = [ - new LdaDyn(objReg), + new EcmaStlettoglobalrecord('obj'), + new EcmaTryldglobalbyname('obj'), new StaDyn(objReg), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(prop1Reg), new LdaiDyn(new Imm(ResultType.Int, 2)), - new Add2Dyn(prop1Reg), + new EcmaAdd2dyn(prop1Reg), new StaDyn(val), - new LdObjByValue(objReg, val) + new EcmaLdobjbyvalue(objReg, val) ]; - - insns = insns.slice(2, insns.length - 1); // cut off let obj and return.dyn + insns = insns.slice(1, insns.length - 1); // cut off let obj and return.dyn expect(checkInstructions(insns, expected)).to.be.true; }); }); diff --git a/ts2panda/tests/expression/functionExpression.test.ts b/ts2panda/tests/expression/functionExpression.test.ts index 1d349b0d25..f7cdaa4e5a 100755 --- a/ts2panda/tests/expression/functionExpression.test.ts +++ b/ts2panda/tests/expression/functionExpression.test.ts @@ -14,42 +14,41 @@ */ import { expect } from 'chai'; -import { DiagnosticCode } from '../../src/diagnostic'; +import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; import { - Add2Dyn, - AsyncFunctionAwaitUncaughtDyn, - AsyncFunctionEnterDyn, - AsyncFunctionRejectDyn, - AsyncFunctionResolveDyn, - Call0Dyn, - CreateGeneratorObjDyn, - CreateIterResultObjectDyn, - DefineAsyncFuncDyn, - DefinefuncDyn, - DefineGeneratorfuncDyn, - DefineNCFuncDyn, - EqDyn, - GetResumeModeDyn, + EcmaAdd2dyn, + EcmaAsyncfunctionawaituncaught, + EcmaAsyncfunctionenter, + EcmaAsyncfunctionreject, + EcmaAsyncfunctionresolve, + EcmaCallarg0dyn, + EcmaCreategeneratorobj, + EcmaCreateiterresultobj, + EcmaDefinefuncdyn, + EcmaDefinegeneratorfunc, + EcmaDefinencfuncdyn, + EcmaEqdyn, + EcmaGetresumemode, + EcmaLdlexenvdyn, + EcmaResumegenerator, + EcmaReturnundefined, + EcmaSuspendgenerator, + EcmaThrowdyn, Imm, Jeqz, Label, LdaDyn, LdaiDyn, - LdLexEnv, ResultType, - ResumeGeneratorDyn, ReturnDyn, - ReturnUndefined, StaDyn, - SuspendGeneratorDyn, - ThrowDyn, VReg } from "../../src/irnodes"; import { CacheExpander } from '../../src/pass/cacheExpander'; import { checkInstructions, compileAllSnippet } from "../utils/base"; -describe("compileFunctionExpression", function() { - it("FunctionExpression with name", function() { +describe("compileFunctionExpression", function () { + it("FunctionExpression with name", function () { let source: string = ` var a = function test() { test(); @@ -59,17 +58,17 @@ describe("compileFunctionExpression", function() { let pandaGens = compileAllSnippet(source, passes); let expected_func = [ - new LdLexEnv(), + new EcmaLdlexenvdyn(), new StaDyn(new VReg()), new LdaDyn(new VReg()), new StaDyn(new VReg()), - new Call0Dyn(new VReg()), - new ReturnUndefined() + new EcmaCallarg0dyn(new VReg()), + new EcmaReturnundefined() ]; let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_test_1") { + if (pg.internalName == "test") { expect(checkInstructions(pg.getInsns(), expected_func), "check func insns").to.be.true; checkCount++; } @@ -78,7 +77,7 @@ describe("compileFunctionExpression", function() { expect(checkCount).to.equals(1); }); - it("FunctionExpression without name", function() { + it("FunctionExpression without name", function () { let source: string = ` var a = function () { }`; @@ -87,15 +86,15 @@ describe("compileFunctionExpression", function() { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_a_1") { + if (pg.internalName == "a") { checkCount++; } if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefinefuncDyn) { - expect(insns.operands[0]).to.equal('func_a_1'); + if (insns instanceof EcmaDefinefuncdyn) { + expect(insns.operands[0]).to.equal('a'); checkCount++; } }); @@ -105,7 +104,7 @@ describe("compileFunctionExpression", function() { expect(checkCount).to.equals(2); }); - it("FunctionExpression without name in binary expression", function() { + it("FunctionExpression without name in binary expression", function () { let source: string = ` var a; a = function () { @@ -115,15 +114,15 @@ describe("compileFunctionExpression", function() { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_a_1") { + if (pg.internalName == "a") { checkCount++; } if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefinefuncDyn) { - expect(insns.operands[0]).to.equal('func_a_1'); + if (insns instanceof EcmaDefinefuncdyn) { + expect(insns.operands[0]).to.equal('a'); checkCount++; } }); @@ -134,7 +133,7 @@ describe("compileFunctionExpression", function() { }); - it("ArrowFunction", function() { + it("ArrowFunction", function () { let source: string = ` var a = ()=> { }`; @@ -143,15 +142,15 @@ describe("compileFunctionExpression", function() { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_a_1") { + if (pg.internalName == "a") { checkCount++; } if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefineNCFuncDyn) { - expect(insns.operands[0]).to.equal('func_a_1'); + if (insns instanceof EcmaDefinencfuncdyn) { + expect(insns.operands[0]).to.equal('a'); checkCount++; } }); @@ -161,7 +160,7 @@ describe("compileFunctionExpression", function() { expect(checkCount).to.equals(2); }); - it("ArrowFunctionWithExpression", function() { + it("ArrowFunctionWithExpression", function () { let source: string = ` var p = (x, y) => x + y;`; @@ -172,14 +171,14 @@ describe("compileFunctionExpression", function() { new LdaDyn(new VReg()), new StaDyn(new VReg()), new LdaDyn(new VReg()), - new Add2Dyn(new VReg()), + new EcmaAdd2dyn(new VReg()), new StaDyn(new VReg()), new LdaDyn(new VReg()), new ReturnDyn() ]; pandaGens.forEach((pg) => { - if (pg.internalName == "func_p_1") { + if (pg.internalName == "p") { expect(checkInstructions(pg.getInsns(), expected_func), "check arrow func insns").to.be.true; checkCount++; } @@ -187,8 +186,8 @@ describe("compileFunctionExpression", function() { if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefineNCFuncDyn) { - expect(insns.operands[0]).to.equal('func_p_1'); + if (insns instanceof EcmaDefinencfuncdyn) { + expect(insns.operands[0]).to.equal('p'); checkCount++; } }); @@ -198,7 +197,7 @@ describe("compileFunctionExpression", function() { expect(checkCount).to.equals(2); }); - it("ArrowFunctionSyntaxError", function() { + it("ArrowFunctionSyntaxError", function () { let source: string = ` var af = x => {};`; @@ -206,13 +205,14 @@ describe("compileFunctionExpression", function() { try { compileAllSnippet(source); } catch (err) { - expect(err.code).to.equal(DiagnosticCode.Line_terminator_not_permitted_before_arrow); + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.Line_terminator_not_permitted_before_arrow); errorThrown = true; } expect(errorThrown).to.be.true; }); - it("GeneratorFunction", function() { + it("GeneratorFunction", function () { let source: string = ` function* a() { yield 1; @@ -224,70 +224,70 @@ describe("compileFunctionExpression", function() { let notThrowLabel1 = new Label(); let expected_func = [ - new CreateGeneratorObjDyn(new VReg()), + new EcmaCreategeneratorobj(new VReg()), new StaDyn(new VReg()), - new SuspendGeneratorDyn(new VReg(), new VReg()), - new ResumeGeneratorDyn(new VReg()), + new EcmaSuspendgenerator(new VReg(), new VReg()), + new EcmaResumegenerator(new VReg()), new StaDyn(new VReg()), - new GetResumeModeDyn(new VReg()), + new EcmaGetresumemode(new VReg()), new StaDyn(new VReg()), new LdaiDyn(new Imm(ResultType.Int, 0)), - new EqDyn(new VReg()), + new EcmaEqdyn(new VReg()), new Jeqz(notRetLabel0), new LdaDyn(new VReg()), new ReturnDyn(), notRetLabel0, new LdaiDyn(new Imm(ResultType.Int, 1)), - new EqDyn(new VReg()), + new EcmaEqdyn(new VReg()), new Jeqz(notThrowLabel0), new LdaDyn(new VReg()), - new ThrowDyn(), + new EcmaThrowdyn(), notThrowLabel0, new LdaDyn(new VReg()), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(new VReg()), - new CreateIterResultObjectDyn(new VReg(), new VReg()), + new EcmaCreateiterresultobj(new VReg(), new VReg()), new StaDyn(new VReg()), - new SuspendGeneratorDyn(new VReg(), new VReg()), - new ResumeGeneratorDyn(new VReg()), + new EcmaSuspendgenerator(new VReg(), new VReg()), + new EcmaResumegenerator(new VReg()), new StaDyn(new VReg()), - new GetResumeModeDyn(new VReg()), + new EcmaGetresumemode(new VReg()), new StaDyn(new VReg()), new LdaiDyn(new Imm(ResultType.Int, 0)), - new EqDyn(new VReg()), + new EcmaEqdyn(new VReg()), new Jeqz(notRetLabel1), new LdaDyn(new VReg()), new ReturnDyn(), notRetLabel1, new LdaiDyn(new Imm(ResultType.Int, 1)), - new EqDyn(new VReg()), + new EcmaEqdyn(new VReg()), new Jeqz(notThrowLabel1), new LdaDyn(new VReg()), - new ThrowDyn(), + new EcmaThrowdyn(), notThrowLabel1, new LdaDyn(new VReg()), - new ReturnUndefined() + new EcmaReturnundefined() ]; let pandaGens = compileAllSnippet(source); let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_a_1") { + if (pg.internalName == "a") { expect(checkInstructions(pg.getInsns(), expected_func), "check generator func insns").to.be.true; checkCount++; } if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefineGeneratorfuncDyn) { - expect(insns.operands[0]).to.equal('func_a_1'); + if (insns instanceof EcmaDefinegeneratorfunc) { + expect(insns.operands[0]).to.equal('a'); checkCount++; } }); @@ -297,7 +297,7 @@ describe("compileFunctionExpression", function() { expect(checkCount).to.equals(2); }); - it("AsyncFunction", function() { + it("AsyncFunction", function () { let source: string = ` async function a() { await 1; @@ -308,30 +308,30 @@ describe("compileFunctionExpression", function() { let nextLabel = new Label(); let expected_func = [ - new AsyncFunctionEnterDyn(), + new EcmaAsyncfunctionenter(), new StaDyn(new VReg()), beginLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(new VReg()), - new AsyncFunctionAwaitUncaughtDyn(new VReg(), new VReg()), + new EcmaAsyncfunctionawaituncaught(new VReg(), new VReg()), new StaDyn(new VReg()), - new SuspendGeneratorDyn(new VReg(), new VReg()), - new ResumeGeneratorDyn(new VReg()), + new EcmaSuspendgenerator(new VReg(), new VReg()), + new EcmaResumegenerator(new VReg()), new StaDyn(new VReg()), - new GetResumeModeDyn(new VReg()), + new EcmaGetresumemode(new VReg()), new StaDyn(new VReg()), new LdaiDyn(new Imm(ResultType.Int, 1)), - new EqDyn(new VReg()), + new EcmaEqdyn(new VReg()), new Jeqz(nextLabel), new LdaDyn(new VReg()), - new ThrowDyn(), + new EcmaThrowdyn(), nextLabel, new LdaDyn(new VReg()), - new AsyncFunctionResolveDyn(new VReg(), new VReg(), new VReg()), + new EcmaAsyncfunctionresolve(new VReg(), new VReg(), new VReg()), new ReturnDyn(), endLabel, new StaDyn(new VReg()), - new AsyncFunctionRejectDyn(new VReg(), new VReg(), new VReg()), + new EcmaAsyncfunctionreject(new VReg(), new VReg(), new VReg()), new ReturnDyn(), ]; @@ -339,31 +339,32 @@ describe("compileFunctionExpression", function() { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "func_a_1") { + if (pg.internalName == "a") { expect(checkInstructions(pg.getInsns(), expected_func), "check async func insns").to.be.true; checkCount++; } if (pg.internalName == "func_main_0") { pg.getInsns().forEach((insns) => { - if (insns instanceof DefineAsyncFuncDyn) { - expect(insns.operands[0]).to.equal('func_a_1'); + if (insns instanceof EcmaDefinencfuncdyn) { + expect(insns.operands[0]).to.equal('a'); checkCount++; } }); } }); - expect(checkCount).to.equals(2); + expect(checkCount).to.equals(1); }); - it("FunctionWithRestParameterSyntaxError", function() { + it("FunctionWithRestParameterSyntaxError", function () { let source: string = `function func(...a,)`; let errorThrown = false; try { compileAllSnippet(source); } catch (err) { - expect(err.code).to.equal(DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); errorThrown = true; } expect(errorThrown).to.be.true; diff --git a/ts2panda/tests/literal.test.ts b/ts2panda/tests/expression/literal.test.ts similarity index 48% rename from ts2panda/tests/literal.test.ts rename to ts2panda/tests/expression/literal.test.ts index 2f91e12fe6..7b4936bfb9 100644 --- a/ts2panda/tests/literal.test.ts +++ b/ts2panda/tests/expression/literal.test.ts @@ -17,347 +17,271 @@ import { expect } from 'chai'; import 'mocha'; -import { DiagnosticCode } from '../src/diagnostic'; +import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; import { - Add2Dyn, - CreateArrayWithBuffer, - CreateEmptyArray, - CreateEmptyObject, - CreateObjectWithBuffer, + EcmaAdd2dyn, + EcmaCreatearraywithbuffer, + EcmaCreateemptyarray, + EcmaCreateemptyobject, + EcmaCreateobjectwithbuffer, + EcmaIncdyn, + EcmaReturnundefined, + EcmaStarrayspread, + EcmaStlettoglobalrecord, + EcmaStownbyindex, + EcmaStownbyname, + EcmaStownbyvalue, + EcmaTryldglobalbyname, Imm, - IncDyn, LdaDyn, LdaiDyn, LdaStr, - MovDyn, - NewObjDynRange, ResultType, - ReturnUndefined, StaDyn, - StArraySpread, - StOwnByIndex, - StOwnByName, - StOwnByValue, - TryLdGlobalByName, VReg -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("LiteralTest", function() { - it("5", function() { +describe("LiteralTest", function () { + it("5", function () { let insns = compileMainSnippet("5"); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 5)), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("\"stringLiteral\"", function() { + it("\"stringLiteral\"", function () { let insns = compileMainSnippet("\"stringLiteral\""); let expected = [ new LdaStr("stringLiteral"), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("true", function() { + it("true", function () { let insns = compileMainSnippet("true"); let expected = [ new LdaDyn(new VReg()), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("false", function() { + it("false", function () { let insns = compileMainSnippet("false"); let expected = [ new LdaDyn(new VReg()), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("null", function() { + it("null", function () { let insns = compileMainSnippet("null"); let expected = [ new LdaDyn(new VReg()), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = [1]", function() { + it("let arr = [1]", function () { let insns = compileMainSnippet("let arr = [1]"); let arrayInstance = new VReg(); - let arrayReg = new VReg(); let expected = [ - new CreateArrayWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(arrayInstance), new LdaDyn(arrayInstance), - new StaDyn(arrayReg), - new ReturnUndefined() + new EcmaStlettoglobalrecord('arr'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = []", function() { + it("let arr = []", function () { let insns = compileMainSnippet("let arr = []"); let arrayInstance = new VReg(); - let arrayReg = new VReg(); let expected = [ - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(arrayInstance), - new StaDyn(arrayReg), - new ReturnUndefined() + new EcmaStlettoglobalrecord('arr'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = [1, 2]", function() { + it("let arr = [1, 2]", function () { let insns = compileMainSnippet("let arr = [1, 2]"); let arrayInstance = new VReg(); let expected = [ - new CreateArrayWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(arrayInstance), new LdaDyn(arrayInstance), + new EcmaStlettoglobalrecord('arr'), + new EcmaReturnundefined() ]; - insns = insns.slice(0, insns.length - 2); + insns = insns.slice(0, insns.length); expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = [, 1]", function() { + it("let arr = [, 1]", function () { let insns = compileMainSnippet("let arr = [, 1]"); - let elemIdxReg = new VReg(); let arrayInstance = new VReg(); - let targetReg = new VReg(); let expected = [ - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(arrayInstance), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(targetReg), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(elemIdxReg), - new LdaDyn(targetReg), - new StOwnByIndex(arrayInstance, elemIdxReg), - new LdaDyn(arrayInstance) + new EcmaStownbyindex(arrayInstance, new Imm(ResultType.Int, 1)), + new LdaDyn(arrayInstance), + new EcmaStlettoglobalrecord('arr'), + new EcmaReturnundefined() ]; - insns = insns.slice(0, insns.length - 2); + insns = insns.slice(0, insns.length); expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = [1, , 3]", function() { + it("let arr = [1, , 3]", function () { let insns = compileMainSnippet("let arr = [1,, 3]"); - let elemIdxReg = new VReg(); let arrayInstance = new VReg(); - let targetReg = new VReg(); let expected = [ - new CreateArrayWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(arrayInstance), new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(targetReg), - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(elemIdxReg), - new LdaDyn(targetReg), - new StOwnByIndex(arrayInstance, elemIdxReg), - new LdaDyn(arrayInstance) + new EcmaStownbyindex(arrayInstance, new Imm(ResultType.Int, 2)), + new LdaDyn(arrayInstance), + new EcmaStlettoglobalrecord('arr'), + new EcmaReturnundefined() ]; - insns = insns.slice(0, insns.length - 2); + insns = insns.slice(0, insns.length); expect(checkInstructions(insns, expected)).to.be.true; }); - it("let arr = [1, ...arr1, 3]", function() { + it("let arr = [1, ...arr1, 3]", function () { let insns = compileMainSnippet(`let arr1 = [1, 2]; let arr = [1, ...arr1, 3]`); - let arr = new VReg(); let elemIdxReg = new VReg(); let arrayInstance = new VReg(); let expected = [ - new CreateArrayWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(arrayInstance), new LdaDyn(arrayInstance), - new StaDyn(arr), + new EcmaStlettoglobalrecord('arr1'), - new CreateArrayWithBuffer(new Imm(ResultType.Int, 1)), + new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, 1)), new StaDyn(arrayInstance), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(elemIdxReg), - new LdaDyn(arr), - new StArraySpread(arrayInstance, elemIdxReg), + new EcmaTryldglobalbyname('arr1'), + new EcmaStarrayspread(arrayInstance, elemIdxReg), new StaDyn(elemIdxReg), new LdaiDyn(new Imm(ResultType.Int, 3)), - new StOwnByValue(arrayInstance, elemIdxReg), - new IncDyn(elemIdxReg), + new EcmaStownbyvalue(arrayInstance, elemIdxReg), + new EcmaIncdyn(elemIdxReg), new StaDyn(elemIdxReg), new LdaDyn(arrayInstance), + new EcmaStlettoglobalrecord('arr'), ]; - insns = insns.slice(0, insns.length - 2); + insns = insns.slice(0, insns.length - 1); expect(checkInstructions(insns, expected)).to.be.true; }); - it("let obj = {}", function() { + it("let obj = {}", function () { let insns = compileMainSnippet("let obj = {}"); let objInstance = new VReg(); - let obj = new VReg(); let expected = [ - new CreateEmptyObject(), + new EcmaCreateemptyobject(), new StaDyn(objInstance), - new StaDyn(obj), - new ReturnUndefined() + new EcmaStlettoglobalrecord('obj'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let obj = {a: 1}", function() { + it("let obj = {a: 1}", function () { let insns = compileMainSnippet("let obj = {a: 1}"); let objInstance = new VReg(); - let obj = new VReg(); - let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaDyn(objInstance), - new StaDyn(obj), - new ReturnUndefined() + new EcmaStlettoglobalrecord('obj'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let obj = {0: 1 + 2}", function() { + it("let obj = {0: 1 + 2}", function () { let insns = compileMainSnippet("let obj = {0: 1 + 2}"); let objInstance = new VReg(); let lhs = new VReg(); - let elemIndex = new VReg(); - let obj = new VReg(); - let targetReg = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(lhs), new LdaiDyn(new Imm(ResultType.Int, 2)), - new Add2Dyn(lhs), - new StaDyn(targetReg), - new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(elemIndex), - new LdaDyn(targetReg), - new StOwnByIndex(objInstance, elemIndex), + new EcmaAdd2dyn(lhs), + new EcmaStownbyindex(objInstance, new Imm(ResultType.Int, 0)), new LdaDyn(objInstance), - new StaDyn(obj), - new ReturnUndefined() + new EcmaStlettoglobalrecord('obj'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let obj = {\"str\": 1}", function() { + it("let obj = {\"str\": 1}", function () { let insns = compileMainSnippet("let obj = {\"str\": 1}"); let objInstance = new VReg(); - let obj = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaDyn(objInstance), - new StaDyn(obj), - new ReturnUndefined() + new EcmaStlettoglobalrecord('obj'), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("let a; let obj = {a}", function() { + it("let a; let obj = {a}", function () { let insns = compileMainSnippet("let a; let obj = {a}"); let objInstance = new VReg(); - let obj = new VReg(); - let a = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), - new LdaDyn(a), - new StOwnByName("a", objInstance), + new EcmaTryldglobalbyname('a'), + new EcmaStownbyname("a", objInstance), new LdaDyn(objInstance), - new StaDyn(obj) + new EcmaStlettoglobalrecord('obj') ]; insns = insns.slice(2, insns.length - 1); expect(checkInstructions(insns, expected)).to.be.true; }); - it("duplicate __proto__", function() { + it("duplicate __proto__", function () { let errorThrown = false; try { compileMainSnippet("({__proto__: null,other: null,'__proto__': null});"); } catch (err) { - expect(err.code).to.equal(DiagnosticCode.Duplicate_identifier_0); + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.Duplicate_identifier_0); errorThrown = true; } expect(errorThrown).to.be.true; }); }); -describe("Regular Expression", function() { - it("let a = /abc/;", function() { - let insns = compileMainSnippet("let a = /abc/;"); - insns = insns.slice(0, insns.length - 1); - let ctorReg = new VReg(); - let regexpReg = new VReg(); - let regexpInstance = new VReg(); - let targetReg = new VReg(); - - let expected = [ - new TryLdGlobalByName("RegExp"), - new StaDyn(ctorReg), - new MovDyn(targetReg, ctorReg), - new LdaStr("abc"), - new StaDyn(regexpReg), - new NewObjDynRange(new Imm(ResultType.Int, 3), [ctorReg, targetReg, regexpReg]), - new StaDyn(regexpInstance), - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("let a = /abc/i;", function() { - let insns = compileMainSnippet("let a = /abc/i;"); - insns = insns.slice(0, insns.length - 1); - let ctorReg = new VReg(); - let patternReg = new VReg(); - let flagsReg = new VReg(); - let regexpInstance = new VReg(); - let targetReg = new VReg(); - - let expected = [ - new TryLdGlobalByName("RegExp"), - new StaDyn(ctorReg), - new MovDyn(targetReg, ctorReg), - new LdaStr("abc"), - new StaDyn(patternReg), - new LdaStr("i"), - new StaDyn(flagsReg), - new NewObjDynRange(new Imm(ResultType.Int, 4), [ctorReg, targetReg, patternReg, flagsReg]), - new StaDyn(regexpInstance), - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("let a = /abc;", function() { - let errorThrown = false; - try { - let insns = compileMainSnippet("let a = /abc;"); - } catch (err) { - expect(err.message).to.equal("Invalid regular expression: /abc;: Unterminated regular expression"); - errorThrown = true; - } - expect(errorThrown).to.be.true; - }); -}); diff --git a/ts2panda/tests/expression/logicBinary.test.ts b/ts2panda/tests/expression/logicBinary.test.ts new file mode 100644 index 0000000000..54e54b96ae --- /dev/null +++ b/ts2panda/tests/expression/logicBinary.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaIsfalse, + EcmaIstrue, + EcmaReturnundefined, + Imm, + Jeqz, + Jmp, + Label, + LdaDyn, + LdaiDyn, ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + + +describe("LogicBinaryOperators", function () { + it("ampersandAmpersand", function () { + let insns = compileMainSnippet("8 && false;"); + let lhs = new VReg(); + let preLabel = new Label(); + let postLabel = new Label(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 8)), + new StaDyn(lhs), + new EcmaIstrue(), + new Jeqz(preLabel), + new LdaDyn(new VReg()), + new Jmp(postLabel), + preLabel, + new LdaDyn(lhs), + postLabel, + new EcmaReturnundefined() + ] + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("barBar", function () { + let insns = compileMainSnippet("8 || false;"); + let lhs = new VReg(); + let preLabel = new Label(); + let postLabel = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 8)), + new StaDyn(lhs), + new EcmaIsfalse(), + new Jeqz(preLabel), + new LdaDyn(new VReg()), + new Jmp(postLabel), + preLabel, + new LdaDyn(lhs), + postLabel, + new EcmaReturnundefined() + ] + + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); diff --git a/ts2panda/tests/expression/new.test.ts b/ts2panda/tests/expression/new.test.ts index f81909c89a..e2440dae8f 100755 --- a/ts2panda/tests/expression/new.test.ts +++ b/ts2panda/tests/expression/new.test.ts @@ -18,83 +18,83 @@ import { } from 'chai'; import 'mocha'; import { - CreateEmptyArray, + EcmaCreateemptyarray, + EcmaLdobjbyname, + EcmaNewobjdynrange, + EcmaNewobjspreaddyn, + EcmaReturnundefined, + EcmaStarrayspread, + EcmaTryldglobalbyname, Imm, LdaDyn, LdaiDyn, - LdObjByName, MovDyn, - NewObjDynRange, - NewobjSpread, ResultType, - ReturnUndefined, StaDyn, - StArraySpread, - TryLdGlobalByName, VReg } from "../../src/irnodes"; import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("NewTest", function() { - it("new Object", function() { +describe("NewTest", function () { + it("new Object", function () { let insns = compileMainSnippet("new Object"); let arg0 = new VReg(); let targetReg = new VReg(); let expected = [ - new TryLdGlobalByName("Object"), + new EcmaTryldglobalbyname("Object"), new StaDyn(arg0), new MovDyn(targetReg, arg0), - new NewObjDynRange(new Imm(ResultType.Int, 2), [arg0, targetReg]), + new EcmaNewobjdynrange(new Imm(ResultType.Int, 2), [arg0, targetReg]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("new Object()", function() { + it("new Object()", function () { let insns = compileMainSnippet("new Object()"); let arg0 = new VReg(); let targetReg = new VReg(); let expected = [ - new TryLdGlobalByName("Object"), + new EcmaTryldglobalbyname("Object"), new StaDyn(arg0), new MovDyn(targetReg, arg0), - new NewObjDynRange(new Imm(ResultType.Int, 2), [arg0, targetReg]), + new EcmaNewobjdynrange(new Imm(ResultType.Int, 2), [arg0, targetReg]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("new Object(2)", function() { + it("new Object(2)", function () { let insns = compileMainSnippet("new Object(2)"); let arg0 = new VReg(); let arg1 = new VReg(); let targetReg = new VReg(); let expected = [ - new TryLdGlobalByName("Object"), + new EcmaTryldglobalbyname("Object"), new StaDyn(arg0), new MovDyn(targetReg, arg0), new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(arg1), - new NewObjDynRange(new Imm(ResultType.Int, 3), [arg0, targetReg, arg1]), + new EcmaNewobjdynrange(new Imm(ResultType.Int, 3), [arg0, targetReg, arg1]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("new obj.ctor()", function() { + it("new obj.ctor()", function () { let insns = compileMainSnippet("let obj; new obj.ctor()"); let obj = new VReg(); let arg0 = new VReg(); @@ -102,14 +102,14 @@ describe("NewTest", function() { let targetReg = new VReg(); let expected = [ - new LdaDyn(obj), + new EcmaTryldglobalbyname('obj'), new StaDyn(temp), - new LdObjByName("ctor", obj), + new EcmaLdobjbyname("ctor", obj), new StaDyn(arg0), new MovDyn(targetReg, arg0), - new NewObjDynRange(new Imm(ResultType.Int, 2), [arg0, targetReg]), + new EcmaNewobjdynrange(new Imm(ResultType.Int, 2), [arg0, targetReg]), ]; insns = insns.slice(2, insns.length - 1); @@ -117,7 +117,7 @@ describe("NewTest", function() { expect(checkInstructions(insns, expected)).to.be.true; }); - it("new Object(...args)", function() { + it("new Object(...args)", function () { let insns = compileMainSnippet(`new Object(...args);`); let arg0 = new VReg(); let elemIdxReg = new VReg(); @@ -125,23 +125,23 @@ describe("NewTest", function() { let arrayInstance = new VReg(); let expected = [ - new TryLdGlobalByName("Object"), + new EcmaTryldglobalbyname("Object"), new StaDyn(arg0), new MovDyn(targetReg, arg0), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(arrayInstance), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(elemIdxReg), - new TryLdGlobalByName("args"), - new StArraySpread(arrayInstance, elemIdxReg), + new EcmaTryldglobalbyname("args"), + new EcmaStarrayspread(arrayInstance, elemIdxReg), new StaDyn(elemIdxReg), new LdaDyn(arrayInstance), - new NewobjSpread(arg0, targetReg), + new EcmaNewobjspreaddyn(arg0, targetReg), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; diff --git a/ts2panda/tests/expression/numericLiteral.test.ts b/ts2panda/tests/expression/numericLiteral.test.ts index cd6383d014..e8c3e842e3 100755 --- a/ts2panda/tests/expression/numericLiteral.test.ts +++ b/ts2panda/tests/expression/numericLiteral.test.ts @@ -27,8 +27,8 @@ import { import { PandaGen } from "../../src/pandagen"; import { checkInstructions } from "../utils/base"; -describe("compileNumericLiteral", function() { - it("NaN", function() { +describe("compileNumericLiteral", function () { + it("NaN", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.NumericLiteral = ts.createNumericLiteral("NaN"); compileNumericLiteral(pandaGen, node); @@ -37,7 +37,7 @@ describe("compileNumericLiteral", function() { expect(checkInstructions(insns, expected)).to.be.true; }); - it("Infinity", function() { + it("Infinity", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.NumericLiteral = ts.createNumericLiteral("10e10000"); compileNumericLiteral(pandaGen, node); @@ -45,7 +45,7 @@ describe("compileNumericLiteral", function() { let expected = [new LdaDyn(new VReg())]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("int", function() { + it("int", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.NumericLiteral = ts.createNumericLiteral("1"); compileNumericLiteral(pandaGen, node); @@ -53,7 +53,7 @@ describe("compileNumericLiteral", function() { let expected = [new LdaiDyn(new Imm(ResultType.Int, 1))]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("Integer overflow", function() { + it("Integer overflow", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.NumericLiteral = ts.createNumericLiteral("2147483648"); compileNumericLiteral(pandaGen, node); @@ -61,7 +61,7 @@ describe("compileNumericLiteral", function() { let expected = [new FldaiDyn(new Imm(ResultType.Float, 2147483648))]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("double", function() { + it("double", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.NumericLiteral = ts.createNumericLiteral("1.1"); compileNumericLiteral(pandaGen, node); diff --git a/ts2panda/tests/expression/operationEqual.test.ts b/ts2panda/tests/expression/operationEqual.test.ts new file mode 100644 index 0000000000..64dfb2fadf --- /dev/null +++ b/ts2panda/tests/expression/operationEqual.test.ts @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaAdd2dyn, + EcmaAshr2dyn, + EcmaDiv2dyn, + EcmaExpdyn, + EcmaMod2dyn, + EcmaMul2dyn, + EcmaReturnundefined, + EcmaShl2dyn, + EcmaShr2dyn, + EcmaStlettoglobalrecord, + EcmaSub2dyn, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + Imm, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("OperationEqualTest", function () { + it("plusEqual", function () { + let insns = compileMainSnippet("let a = 2;\n" + + "a += 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaAdd2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("minusEqual", function () { + let insns = compileMainSnippet("let a = 5;\n" + + "a -= 7;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 7)), + new EcmaSub2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("asteriskEqual", function () { + let insns = compileMainSnippet("let a = 2;\n" + + "a *= 4;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 4)), + new EcmaMul2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("AsteriskAsteriskEqualsToken", function () { + let insns = compileMainSnippet("let a = 2;\n" + + "a **= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaExpdyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ] + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("slashEqual", function () { + let insns = compileMainSnippet("let a = 5;\n" + + "a /= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaDiv2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("percentEqual", function () { + let insns = compileMainSnippet("let a = 15;\n" + + "a %= 7;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 15)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 7)), + new EcmaMod2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("lessThanLessThanEqual", function () { + let insns = compileMainSnippet("let a = 8;\n" + + "a <<= 3;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 8)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 3)), + new EcmaShl2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("greaterThanGreaterThanEqual", function () { + let insns = compileMainSnippet("let a = 4;\n" + + "a >>= 1;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 4)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaShr2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("greaterThanGreaterThanGreaterThanEqual", function () { + let insns = compileMainSnippet("let a = 8;\n" + + "a >>>= 2;"); + let lhs = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 8)), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaAshr2dyn(lhs), + new EcmaTrystglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); diff --git a/ts2panda/tests/expression/parenthesized.test.ts b/ts2panda/tests/expression/parenthesized.test.ts new file mode 100644 index 0000000000..370d10e751 --- /dev/null +++ b/ts2panda/tests/expression/parenthesized.test.ts @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, + LdaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("ParenthesizedExpressionTest", function () { + it("(a)", function () { + let insns = compileMainSnippet("let a; (a);"); + let a = new VReg(); + let expected = [ + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("(((a)))", function () { + let insns = compileMainSnippet("let a; (((a)))"); + let a = new VReg(); + let expected = [ + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/expression/postfixOperations.test.ts b/ts2panda/tests/expression/postfixOperations.test.ts new file mode 100644 index 0000000000..df76e7bc47 --- /dev/null +++ b/ts2panda/tests/expression/postfixOperations.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaDecdyn, + EcmaIncdyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTonumber, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + Imm, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("PostfixOperationsTest", function () { + it("let i = 0; i++", function () { + let insns = compileMainSnippet("let i = 5; i++"); + let i = new VReg(); + let temp = new VReg(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaIncdyn(temp), + new EcmaTrystglobalbyname('i'), + new EcmaTonumber(i), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("let i = 0; i--", function () { + let insns = compileMainSnippet("let i = 5; i--"); + let i = new VReg(); + let temp = new VReg(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaDecdyn(temp), + new EcmaTrystglobalbyname('i'), + new EcmaTonumber(i), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); + + diff --git a/ts2panda/tests/expression/prefixOperations.test.ts b/ts2panda/tests/expression/prefixOperations.test.ts new file mode 100644 index 0000000000..67f70a550c --- /dev/null +++ b/ts2panda/tests/expression/prefixOperations.test.ts @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaDecdyn, + EcmaIncdyn, + EcmaIstrue, + EcmaNegdyn, + EcmaNotdyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTonumber, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + Imm, + Jeqz, + Jmp, + Label, + LdaDyn, + LdaiDyn, ResultType, StaDyn, VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("PrefixOperationsTest", function () { + it('let i = 5; ++i', function () { + let insns = compileMainSnippet("let i = 5; let j = ++i"); + + let temp = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaIncdyn(temp), + new EcmaTrystglobalbyname('i'), + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('let i = 5; --i', function () { + let insns = compileMainSnippet("let i = 5; let j = --i"); + + let temp = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaDecdyn(temp), + new EcmaTrystglobalbyname('i'), + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('let i = 5; let j = +i', function () { + let insns = compileMainSnippet("let i = 5; let j = +i"); + + let temp = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaTonumber(temp), + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('let i = 5; let j = -i', function () { + let insns = compileMainSnippet("let i = 5; let j = -i"); + + let temp = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp), + new EcmaNegdyn(temp), + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('let i = 5; let j = !i', function () { + let insns = compileMainSnippet("let i = 5; let j = !i"); + + let preLabel = new Label(); + let postLabel = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(new VReg()), + new EcmaIstrue(), + new Jeqz(preLabel), + new LdaDyn(new VReg()), + new Jmp(postLabel), + preLabel, + new LdaDyn(new VReg()), + postLabel, + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('let i = 5; let j = ~i', function () { + let insns = compileMainSnippet("let i = 5; let j = ~i"); + + let temp_i = new VReg(); + + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaTryldglobalbyname('i'), + new StaDyn(temp_i), + new EcmaNotdyn(temp_i), + new EcmaStlettoglobalrecord('j'), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/propertyAccess.test.ts b/ts2panda/tests/expression/propertyAccess.test.ts similarity index 74% rename from ts2panda/tests/propertyAccess.test.ts rename to ts2panda/tests/expression/propertyAccess.test.ts index 541081e8ec..f63f03003c 100644 --- a/ts2panda/tests/propertyAccess.test.ts +++ b/ts2panda/tests/expression/propertyAccess.test.ts @@ -18,58 +18,59 @@ import { } from 'chai'; import 'mocha'; import { - CreateObjectWithBuffer, - DefineMethod, - DefineGetterSetterByValue, + EcmaCreateobjectwithbuffer, + EcmaDefinegettersetterbyvalue, + EcmaDefinemethod, + EcmaLdobjbyname, + EcmaStobjbyname, + EcmaTryldglobalbyname, Imm, LdaDyn, LdaiDyn, LdaStr, - LdObjByName, MovDyn, ResultType, StaDyn, - StObjByName, VReg -} from "../src/irnodes"; -import { checkInstructions, compileAllSnippet, compileMainSnippet } from "./utils/base"; +} from "../../src/irnodes"; +import { checkInstructions, compileAllSnippet, compileMainSnippet } from "../utils/base"; -describe("PropertyAccess", function() { - it('get obj.property', function() { +describe("PropertyAccess", function () { + it('get obj.property', function () { let insns = compileMainSnippet(`let obj; obj.property;`); let objReg = new VReg(); let expected = [ - new LdaDyn(objReg), + new EcmaTryldglobalbyname('obj'), new StaDyn(objReg), - new LdObjByName("property", objReg) + new EcmaLdobjbyname("property", objReg) ]; insns = insns.slice(2, insns.length - 1); // cut off let obj and return.dyn expect(checkInstructions(insns, expected)).to.be.true; }); - it('set obj.property', function() { + it('set obj.property', function () { let insns = compileMainSnippet(`let obj; obj.property = 0;`); let objReg = new VReg(); let tempObj = new VReg(); let expected = [ - new LdaDyn(objReg), + new EcmaTryldglobalbyname('obj'), new StaDyn(tempObj), new MovDyn(objReg, tempObj), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StObjByName("property", objReg), + new EcmaStobjbyname("property", objReg), ]; insns = insns.slice(2, insns.length - 1); // cut off let obj and return.dyn expect(checkInstructions(insns, expected)).to.be.true; }); - it('SetAccessor', function() { + it('SetAccessor', function () { let compilerunit = compileAllSnippet(` let obj = { set myMethod (arg) { @@ -82,15 +83,15 @@ describe("PropertyAccess", function() { let propReg = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaDyn(new VReg()), - new DefineMethod("func_myMethod_1", new VReg()), + new EcmaDefinemethod("myMethod", new Imm(ResultType.Int, 1), new VReg()), new StaDyn(funcReg), new LdaStr("myMethod"), new StaDyn(propReg), new LdaDyn(new VReg()), - new DefineGetterSetterByValue(objInstance, propReg, new VReg(), funcReg), + new EcmaDefinegettersetterbyvalue(objInstance, propReg, new VReg(), funcReg), ]; compilerunit.forEach(element => { @@ -101,14 +102,14 @@ describe("PropertyAccess", function() { expect(checkInstructions(insns, expected)).to.be.true; } - if (element.internalName == "func_myMethod_1") { + if (element.internalName == "myMethod") { let parameterLength = element.getParameterLength(); expect(parameterLength == 1).to.be.true; } }); }); - it('GetAccessor', function() { + it('GetAccessor', function () { let compilerunit = compileAllSnippet(` let obj = { get a() { return 'a'; }; @@ -119,15 +120,15 @@ describe("PropertyAccess", function() { let propReg = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaDyn(new VReg()), - new DefineMethod("func_a_1", new VReg()), + new EcmaDefinemethod("a", new Imm(ResultType.Int, 0), new VReg()), new StaDyn(funcReg), new LdaStr("a"), new StaDyn(propReg), new LdaDyn(new VReg()), - new DefineGetterSetterByValue(objInstance, propReg, funcReg, new VReg()), + new EcmaDefinegettersetterbyvalue(objInstance, propReg, funcReg, new VReg()), ]; compilerunit.forEach(element => { @@ -140,7 +141,7 @@ describe("PropertyAccess", function() { }); }); - it('GetAccessor&SetAccessor', function() { + it('GetAccessor&SetAccessor', function () { let compilerunit = compileAllSnippet(`let obj = { get a() { return 'a'; }, set a(x) {} @@ -152,18 +153,18 @@ describe("PropertyAccess", function() { let propReg = new VReg(); let expected = [ - new CreateObjectWithBuffer(new Imm(ResultType.Int, 0)), + new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, 0)), new StaDyn(objInstance), new LdaDyn(new VReg()), - new DefineMethod("func_a_1", new VReg()), + new EcmaDefinemethod("#1#a", new Imm(ResultType.Int, 0), new VReg()), new StaDyn(getterReg), new LdaDyn(new VReg()), - new DefineMethod("func_a_2", new VReg()), + new EcmaDefinemethod("#2#a", new Imm(ResultType.Int, 1), new VReg()), new StaDyn(setterReg), new LdaStr("a"), new StaDyn(propReg), new LdaDyn(new VReg()), - new DefineGetterSetterByValue(objInstance, propReg, getterReg, setterReg), + new EcmaDefinegettersetterbyvalue(objInstance, propReg, getterReg, setterReg), ]; compilerunit.forEach(element => { diff --git a/ts2panda/tests/expression/regular.test.js b/ts2panda/tests/expression/regular.test.js new file mode 100644 index 0000000000..22a0dc7e28 --- /dev/null +++ b/ts2panda/tests/expression/regular.test.js @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaCreateregexpwithliteral, + EcmaStlettoglobalrecord, + Imm, + ResultType +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("Regular Expression", function () { + it("let a = /abc/;", function () { + let insns = compileMainSnippet("let a = /abc/;"); + insns = insns.slice(0, insns.length - 1); + + let expected = [ + new EcmaCreateregexpwithliteral("abc", new Imm(ResultType.Int, 0)), + new EcmaStlettoglobalrecord('a') + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("let a = /abc/i;", function () { + let insns = compileMainSnippet("let a = /abc/i;"); + insns = insns.slice(0, insns.length - 1); + + let expected = [ + new EcmaCreateregexpwithliteral("abc", new Imm(ResultType.Int, 2)), + new EcmaStlettoglobalrecord('a') + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/expression/stringLiteral.test.ts b/ts2panda/tests/expression/stringLiteral.test.ts index b926af8e46..cf56ba16dc 100755 --- a/ts2panda/tests/expression/stringLiteral.test.ts +++ b/ts2panda/tests/expression/stringLiteral.test.ts @@ -22,8 +22,8 @@ import { import { PandaGen } from "../../src/pandagen"; import { checkInstructions } from "../utils/base"; -describe("compileStringLiteral", function() { - it("i am a string", function() { +describe("compileStringLiteral", function () { + it("i am a string", function () { let pandaGen = new PandaGen("ignored", 0, undefined); let node: ts.StringLiteral = ts.createStringLiteral("i am a string"); compileStringLiteral(pandaGen, node); diff --git a/ts2panda/tests/expression/TemplateExpression.test.ts b/ts2panda/tests/expression/templateExpression.test.ts similarity index 70% rename from ts2panda/tests/expression/TemplateExpression.test.ts rename to ts2panda/tests/expression/templateExpression.test.ts index eb892c835f..5654375b5f 100755 --- a/ts2panda/tests/expression/TemplateExpression.test.ts +++ b/ts2panda/tests/expression/templateExpression.test.ts @@ -18,22 +18,22 @@ import { } from 'chai'; import 'mocha'; import { - Add2Dyn, - CalliThisRangeDyn, - GetTemplateObject, + EcmaAdd2dyn, + EcmaCallithisrangedyn, + EcmaCreateemptyarray, + EcmaGettemplateobject, + EcmaLdobjbyname, + EcmaReturnundefined, + EcmaStobjbyvalue, + EcmaTryldglobalbyname, Imm, IRNode, LdaDyn, LdaiDyn, LdaStr, - LdObjByName, MovDyn, ResultType, - ReturnUndefined, StaDyn, - StObjByValue, - TryLdGlobalByName, - CreateEmptyArray, VReg } from "../../src/irnodes"; import { checkInstructions, compileMainSnippet } from "../utils/base"; @@ -45,7 +45,7 @@ function MicroCreateAddInsns(leftVal: number, rightVal: number): IRNode[] { insns.push(new LdaiDyn(new Imm(ResultType.Int, leftVal))); insns.push(new StaDyn(lhs)); insns.push(new LdaiDyn(new Imm(ResultType.Int, rightVal))); - insns.push(new Add2Dyn(lhs)); + insns.push(new EcmaAdd2dyn(lhs)); return insns; } @@ -55,9 +55,9 @@ function MicroCreateObjAndPropInsns(): IRNode[] { let obj = new VReg(); let val = new VReg(); - insns.push(new TryLdGlobalByName("String")); + insns.push(new EcmaTryldglobalbyname("String")); insns.push(new StaDyn(obj)); - insns.push(new LdObjByName("raw", obj)); + insns.push(new EcmaLdobjbyname("raw", obj)); insns.push(new StaDyn(val)); return insns; @@ -68,33 +68,33 @@ function MicroGetTemplateObject(rawArr: VReg, cookedArr: VReg): IRNode[] { let objReg = new VReg(); let indexReg = new VReg(); - insns.push(new CreateEmptyArray()); + insns.push(new EcmaCreateemptyarray()); insns.push(new StaDyn(objReg)); insns.push(new LdaiDyn(new Imm(ResultType.Int, 0))); insns.push(new StaDyn(indexReg)); insns.push(new LdaDyn(rawArr)); - insns.push(new StObjByValue(objReg,indexReg)); + insns.push(new EcmaStobjbyvalue(objReg, indexReg)); insns.push(new LdaiDyn(new Imm(ResultType.Int, 1))); insns.push(new StaDyn(indexReg)); insns.push(new LdaDyn(cookedArr)); - insns.push(new StObjByValue(objReg,indexReg)); - insns.push(new GetTemplateObject(objReg)); + insns.push(new EcmaStobjbyvalue(objReg, indexReg)); + insns.push(new EcmaGettemplateobject(objReg)); return insns; } -describe("templateExpressionTest", function() { - it("`string text line 1`", function() { +describe("templateExpressionTest", function () { + it("`string text line 1`", function () { let insns = compileMainSnippet("`string text line 1`;"); let expected = [ new LdaStr("string text line 1"), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("`Fifteen is ${5 + 10}`", function() { + it("`Fifteen is ${5 + 10}`", function () { let insns = compileMainSnippet("`Fifteen is ${5 + 10}`"); let headVal = new VReg(); @@ -102,13 +102,13 @@ describe("templateExpressionTest", function() { new LdaStr("Fifteen is "), new StaDyn(headVal), ...MicroCreateAddInsns(5, 10), - new Add2Dyn(headVal), - new ReturnUndefined() + new EcmaAdd2dyn(headVal), + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); - it("String.raw`string text line 1`", function() { + it("String.raw`string text line 1`", function () { let insns = compileMainSnippet("String.raw`string text line 1`;"); let obj = new VReg(); let prop = new VReg(); @@ -122,34 +122,34 @@ describe("templateExpressionTest", function() { let expected = [ ...MicroCreateObjAndPropInsns(), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(rawArr), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(cookedArr), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(elemIdxReg), new LdaStr("string text line 1"), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr("string text line 1"), - new StObjByValue(cookedArr, elemIdxReg), - new MovDyn(rawArr1,rawArr), - new MovDyn(cookedArr1,cookedArr), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), + new MovDyn(rawArr1, rawArr), + new MovDyn(cookedArr1, cookedArr), ...MicroGetTemplateObject(rawArr1, cookedArr), new StaDyn(templateObj), // structure call - new CalliThisRangeDyn(new Imm(ResultType.Int, 2), [prop, obj, templateObj]), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 2), [prop, obj, templateObj]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("String.raw`string text line 1\\nstring text line 2`", function() { + it("String.raw`string text line 1\\nstring text line 2`", function () { let insns = compileMainSnippet("String.raw`string text line 1\\nstring text line 2`;"); let obj = new VReg(); let prop = new VReg(); @@ -163,34 +163,34 @@ describe("templateExpressionTest", function() { let expected = [ ...MicroCreateObjAndPropInsns(), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(rawArr), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(cookedArr), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(elemIdxReg), new LdaStr("string text line 1\\nstring text line 2"), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr("string text line 1\nstring text line 2"), - new StObjByValue(cookedArr, elemIdxReg), - new MovDyn(rawArr1,rawArr), - new MovDyn(cookedArr1,cookedArr), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), + new MovDyn(rawArr1, rawArr), + new MovDyn(cookedArr1, cookedArr), ...MicroGetTemplateObject(rawArr1, cookedArr1), new StaDyn(templateObj), // structure call - new CalliThisRangeDyn(new Imm(ResultType.Int, 2), [prop, obj, templateObj]), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 2), [prop, obj, templateObj]), - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("String.raw`Fifteen is ${5 + 10} !!`", function() { + it("String.raw`Fifteen is ${5 + 10} !!`", function () { let insns = compileMainSnippet("String.raw`Fifteen is ${5 + 10} !!`"); let obj = new VReg(); let prop = new VReg(); @@ -205,25 +205,25 @@ describe("templateExpressionTest", function() { let expected = [ ...MicroCreateObjAndPropInsns(), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(rawArr), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(cookedArr), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(elemIdxReg), new LdaStr("Fifteen is "), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr("Fifteen is "), - new StObjByValue(cookedArr, elemIdxReg), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(elemIdxReg), new LdaStr(" !!"), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr(" !!"), - new StObjByValue(cookedArr, elemIdxReg), - new MovDyn(rawArr1,rawArr), - new MovDyn(cookedArr1,cookedArr), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), + new MovDyn(rawArr1, rawArr), + new MovDyn(cookedArr1, cookedArr), ...MicroGetTemplateObject(rawArr1, cookedArr1), new StaDyn(templateObj), @@ -232,13 +232,13 @@ describe("templateExpressionTest", function() { new StaDyn(addRet), // structure call - new CalliThisRangeDyn(new Imm(ResultType.Int, 3), [prop, obj, rawArr, templateObj]), - new ReturnUndefined() + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 3), [prop, obj, rawArr, templateObj]), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("String.raw`Fifteen is ${5 + 10} !!\\n Is not ${15 + 10} !!!`", function() { + it("String.raw`Fifteen is ${5 + 10} !!\\n Is not ${15 + 10} !!!`", function () { let insns = compileMainSnippet("String.raw`Fifteen is ${5 + 10} !!\\n Is not ${15 + 10} !!!\\n`"); let obj = new VReg(); let val = new VReg(); @@ -255,32 +255,32 @@ describe("templateExpressionTest", function() { let expected = [ ...MicroCreateObjAndPropInsns(), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(rawArr), - new CreateEmptyArray(), + new EcmaCreateemptyarray(), new StaDyn(cookedArr), new LdaiDyn(new Imm(ResultType.Int, 0)), new StaDyn(elemIdxReg), new LdaStr("Fifteen is "), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr("Fifteen is "), - new StObjByValue(cookedArr, elemIdxReg), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(elemIdxReg), new LdaStr(" !!\\n Is not "), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr(" !!\n Is not "), - new StObjByValue(cookedArr, elemIdxReg), + new EcmaStobjbyvalue(cookedArr, elemIdxReg), new LdaiDyn(new Imm(ResultType.Int, 2)), new StaDyn(elemIdxReg), new LdaStr(" !!!\\n"), - new StObjByValue(rawArr, elemIdxReg), + new EcmaStobjbyvalue(rawArr, elemIdxReg), new LdaStr(" !!!\n"), - new StObjByValue(cookedArr, elemIdxReg), - new MovDyn(rawArr1,rawArr), - new MovDyn(cookedArr1,cookedArr), - + new EcmaStobjbyvalue(cookedArr, elemIdxReg), + new MovDyn(rawArr1, rawArr), + new MovDyn(cookedArr1, cookedArr), + ...MicroGetTemplateObject(rawArr1, cookedArr1), new StaDyn(templateObj), @@ -290,8 +290,8 @@ describe("templateExpressionTest", function() { new StaDyn(addRet2), // structure call - new CalliThisRangeDyn(new Imm(ResultType.Int, 4), [prop, obj, rawArr, cookedArr, templateObj]), - new ReturnUndefined() + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 4), [prop, obj, rawArr, cookedArr, templateObj]), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/otherExpressions.test.ts b/ts2panda/tests/expression/thisKeyWord.test.ts similarity index 41% rename from ts2panda/tests/otherExpressions.test.ts rename to ts2panda/tests/expression/thisKeyWord.test.ts index 95e69ebc3e..186c2d2b94 100644 --- a/ts2panda/tests/otherExpressions.test.ts +++ b/ts2panda/tests/expression/thisKeyWord.test.ts @@ -1,143 +1,65 @@ -/* - * Copyright (c) 2021 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 { - expect -} from 'chai'; -import 'mocha'; -import { - GetUnmappedArgs, - Imm, - LdaDyn, - LdaiDyn, - LdObjByIndex, - ResultType, - ReturnUndefined, - StaDyn, - VReg -} from "../src/irnodes"; -import { PandaGen } from "../src/pandagen"; -import { LocalVariable } from "../src/variable"; -import { checkInstructions, compileMainSnippet, SnippetCompiler } from "./utils/base"; - -describe("ParenthesizedExpressionTest", function () { - it("(a)", function () { - let insns = compileMainSnippet("let a; (a);"); - let a = new VReg(); - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(a), - new LdaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("(((a)))", function () { - let insns = compileMainSnippet("let a; (((a)))"); - let a = new VReg(); - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(a), - new LdaDyn(a), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); -}); - -describe("ThisKeyword", function () { - let pandaGen: PandaGen; - - beforeEach(function () { - pandaGen = new PandaGen("" /* internalName */, 0 /* number of parameters */); - }); - - it("this in global scope", function () { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("this"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - let expected = [ - new LdaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let thisVar = globalScope!.findLocal("this"); - expect(thisVar instanceof LocalVariable).to.be.true; - }); - - it("this in function scope", function () { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("function a() {this}"); - let functionPg = snippetCompiler.getPandaGenByName("func_a_1"); - let functionScope = functionPg!.getScope(); - let insns = compileMainSnippet("this;", pandaGen, functionScope); - let expected = [ - new LdaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let thisVar = functionScope!.findLocal("this"); - expect(thisVar != undefined).to.be.true; - expect(thisVar instanceof LocalVariable).to.be.true; - }); -}); - -describe("arguments Keyword", function () { - it('arguments: Array-like object accessible inside functions', function () { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(`function foo(a,b) {arguments[0];}`); - let argumentsReg = new VReg(); - let temp1 = new VReg(); - let indexReg = new VReg(); - let expected = [ - new GetUnmappedArgs(), - new StaDyn(argumentsReg), - new LdaDyn(argumentsReg), - new StaDyn(temp1), - new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(indexReg), - new LdObjByIndex(temp1, indexReg), - new ReturnUndefined() - ]; - let functionPg = snippetCompiler.getPandaGenByName("func_foo_1"); - let insns = functionPg!.getInsns(); - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('arguments as parameter shadows keyword', function () { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(`function foo(arguments) {arguments[0];}`); - let parameterArguments = new VReg(); - let temp1 = new VReg(); - let indexReg = new VReg(); - let expected = [ - new GetUnmappedArgs(), - new StaDyn(new VReg()), - new LdaDyn(parameterArguments), - new StaDyn(temp1), - new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(indexReg), - new LdObjByIndex(temp1, indexReg), - new ReturnUndefined() - ]; - let functionPg = snippetCompiler.getPandaGenByName("func_foo_1"); - let insns = functionPg!.getInsns(); - - expect(checkInstructions(insns, expected)).to.be.true; - }); -}); +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaReturnundefined, + LdaDyn, + VReg +} from "../../src/irnodes"; +import { PandaGen } from "../../src/pandagen"; +import { LocalVariable } from "../../src/variable"; +import { checkInstructions, compileMainSnippet, SnippetCompiler } from "../utils/base"; + +describe("ThisKeyword", function () { + let pandaGen: PandaGen; + + beforeEach(function () { + pandaGen = new PandaGen("" /* internalName */, 0 /* number of parameters */); + }); + + it("this in global scope", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("this"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new LdaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let thisVar = globalScope!.findLocal("this"); + expect(thisVar instanceof LocalVariable).to.be.true; + }); + + it("this in function scope", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("function a() {this}"); + let functionPg = snippetCompiler.getPandaGenByName("a"); + let functionScope = functionPg!.getScope(); + let insns = compileMainSnippet("this;", pandaGen, functionScope); + let expected = [ + new LdaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let thisVar = functionScope!.findLocal("this"); + expect(thisVar != undefined).to.be.true; + expect(thisVar instanceof LocalVariable).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/expression/typeOf.test.ts b/ts2panda/tests/expression/typeOf.test.ts new file mode 100644 index 0000000000..d504d51721 --- /dev/null +++ b/ts2panda/tests/expression/typeOf.test.ts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaCallarg1dyn, + EcmaLdobjbyname, + EcmaReturnundefined, + EcmaTryldglobalbyname, + EcmaTypeofdyn, + Imm, + LdaiDyn, + LdaStr, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("TypeOfTest", function () { + it("typeof 12", function () { + let insns = compileMainSnippet("typeof 5"); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaTypeofdyn(), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("typeof Number(\"12\")", function () { + let insns = compileMainSnippet("typeof Number(\"5\")"); + let arg1 = new VReg(); + let arg3 = new VReg(); + let expected = [ + new EcmaTryldglobalbyname("Number"), + new StaDyn(arg1), + + new LdaStr("5"), + new StaDyn(arg3), + new EcmaCallarg1dyn(arg1, arg3), + new EcmaTypeofdyn(), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("typeof x", function () { + let insns = compileMainSnippet("typeof x"); + + let expected = [ + new EcmaLdobjbyname("x", new VReg()), + new EcmaTypeofdyn(), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("typeof(x)", function () { + let insns = compileMainSnippet("typeof(x)"); + + let expected = [ + new EcmaLdobjbyname("x", new VReg()), + new EcmaTypeofdyn(), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); diff --git a/ts2panda/tests/expression/void.test.ts b/ts2panda/tests/expression/void.test.ts new file mode 100644 index 0000000000..330849f16c --- /dev/null +++ b/ts2panda/tests/expression/void.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, + LdaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("voidExpressionTest", function () { + it("void (a)", function () { + let insns = compileMainSnippet("let a; void (a);"); + + let expected = [ + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('a'), + new EcmaTryldglobalbyname('a'), + new LdaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/hoist.test.ts b/ts2panda/tests/hoist.test.ts index bc5d49f7b2..1cb0b35c6e 100644 --- a/ts2panda/tests/hoist.test.ts +++ b/ts2panda/tests/hoist.test.ts @@ -18,8 +18,11 @@ import { } from 'chai'; import 'mocha'; import { - DefinefuncDyn, - EqDyn, + EcmaDefinefuncdyn, + EcmaIstrue, + EcmaReturnundefined, + EcmaStglobalvar, + EcmaThrowundefinedifhole, Imm, Jeqz, Label, @@ -27,139 +30,131 @@ import { LdaiDyn, LdaStr, ResultType, - ReturnUndefined, StaDyn, - StGlobalVar, - ThrowUndefinedIfHole, - Toboolean, VReg } from "../src/irnodes"; import { checkInstructions, compileMainSnippet, SnippetCompiler } from "./utils/base"; -describe("HoistTest", function() { +describe("HoistTest", function () { // case 1: hoist var declared variable ((declared in global scope)) in global scope - it('case 1;', function() { + it('case 1;', function () { let insns = compileMainSnippet("var a = 1;"); let expected = [ new LdaDyn(new VReg()), - new StGlobalVar("a"), + new EcmaStglobalvar("a"), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StGlobalVar("a"), - new ReturnUndefined() + new EcmaStglobalvar("a"), + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); // case 2: hoist var declared variable (declared in local scope) in global scope - it('case 2', function() { + it('case 2', function () { let insns = compileMainSnippet(`if (true) { var a = 2; }`); - let conditionReg = new VReg(); let endLabel = new Label(); let expected = [ new LdaDyn(new VReg()), - new StGlobalVar("a"), + new EcmaStglobalvar("a"), new LdaDyn(new VReg()), - new Toboolean(), - new EqDyn(conditionReg), + new EcmaIstrue(), new Jeqz(endLabel), new LdaiDyn(new Imm(ResultType.Int, 2)), - new StGlobalVar("a"), + new EcmaStglobalvar("a"), endLabel, - new ReturnUndefined() + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); // case 3: hoist function declaration in global scope - it('case 3', function() { + it('case 3', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {};`); let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new DefinefuncDyn("func_a_1", new VReg()), - new StGlobalVar("a"), - new ReturnUndefined() + new EcmaDefinefuncdyn("a", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("a"), + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); // case 4: In case that two function declared directly in global scope with the same name, hoist the later one. - it('case 4', function() { + it('case 4', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {}; function a() {}`); let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new DefinefuncDyn("func_a_2", new VReg()), - new StGlobalVar("a"), - new ReturnUndefined() + new EcmaDefinefuncdyn("#2#a", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("a"), + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); // case 5: hoisting of function declaration is of higher priority than var declared variables with a same name in global scope - it('case 5', function() { + it('case 5', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`var a = 1; function a() {}`); let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new DefinefuncDyn("func_a_1", new VReg()), - new StGlobalVar("a"), + new EcmaDefinefuncdyn("a", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("a"), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StGlobalVar("a"), - new ReturnUndefined() + new EcmaStglobalvar("a"), + new EcmaReturnundefined() ] expect(checkInstructions(insns, expected)).to.be.true; }); // case 6: hoist var declared variable in function scope - it('case 6', function() { + it('case 6', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {var a = 1;}`); - let funcPg = snippetCompiler.getPandaGenByName("func_a_1"); + let funcPg = snippetCompiler.getPandaGenByName("a"); let insns = funcPg!.getInsns(); - let builtInUndefinedVreg = new VReg(); let a = new VReg(); let expected = [ - new LdaDyn(builtInUndefinedVreg), - new StaDyn(a), + new LdaDyn(a), + new StaDyn(new VReg()), new LdaiDyn(new Imm(ResultType.Int, 1)), new StaDyn(a), - new ReturnUndefined() + new EcmaReturnundefined() ] - expect(checkInstructions(insns!, expected)).to.be.true; }); // case 7: hoist function declaration in function scope - it('case 7', function() { + it('case 7', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {function b() {}};`); - let funcPg = snippetCompiler.getPandaGenByName("func_a_1"); + let funcPg = snippetCompiler.getPandaGenByName("a"); let insns = funcPg!.getInsns(); let a = new VReg(); let expected = [ - new DefinefuncDyn("func_b_2", new VReg()), + new EcmaDefinefuncdyn("b", new Imm(ResultType.Int, 0), new VReg()), new StaDyn(a), - new ReturnUndefined() + new EcmaReturnundefined() ] expect(checkInstructions(insns!, expected)).to.be.true; }); // case 8: temporary dead zone of let in global scope - it('case 8', function() { + it('case 8', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`a = 1; let a;`); @@ -169,34 +164,34 @@ describe("HoistTest", function() { let expected = [ new LdaStr("a"), new StaDyn(idReg), - new ThrowUndefinedIfHole(new VReg(), idReg) + new EcmaThrowundefinedifhole(new VReg(), idReg) ] expect(checkInstructions(insns.slice(3, 5), expected)); }); // case 9: temporary dead zone of let in function scope - it('case 9', function() { + it('case 9', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function b() { a = 1; let a; }`); - let funcPg = snippetCompiler.getPandaGenByName("func_b_1"); + let funcPg = snippetCompiler.getPandaGenByName("b"); let insns = funcPg!.getInsns(); let idReg = new VReg(); let expected = [ new LdaStr("a"), new StaDyn(idReg), - new ThrowUndefinedIfHole(new VReg(), idReg) + new EcmaThrowundefinedifhole(new VReg(), idReg) ] expect(checkInstructions(insns.slice(3, 5), expected)); }); // case 10: temporary dead zone of let in local scope - it('case 10', function() { + it('case 10', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`{ a = 1; @@ -209,7 +204,7 @@ describe("HoistTest", function() { let expected = [ new LdaStr("a"), new StaDyn(idReg), - new ThrowUndefinedIfHole(new VReg(), idReg) + new EcmaThrowundefinedifhole(new VReg(), idReg) ] expect(checkInstructions(insns.slice(3, 5), expected)); diff --git a/ts2panda/tests/intrinsicExpander.test.ts b/ts2panda/tests/intrinsicExpander.test.ts index 4dfdab7984..8016811d79 100644 --- a/ts2panda/tests/intrinsicExpander.test.ts +++ b/ts2panda/tests/intrinsicExpander.test.ts @@ -19,31 +19,31 @@ import { import 'mocha'; import { IntrinsicExpanderInternal } from "../src/intrinsicExpander"; import { - And2Dyn, CallShort, + EcmaAnd2dyn, + EcmaShl2dyn, FormatItem, Intrinsic, IRNodeKind, OperandKind, ResultDst, ResultType, - Shl2Dyn, VReg } from "../src/irnodes"; import { checkInstructions } from "./utils/base"; -describe("InstructionExpanderTest", function() { - it("test expander saves acc", function() { +describe("InstructionExpanderTest", function () { + it("test expander saves acc", function () { let expander = new IntrinsicExpanderInternal(); let lhs = new VReg(); - let insns = expander.expandInstruction(new Shl2Dyn(lhs))[0]; + let insns = expander.expandInstruction(new EcmaShl2dyn(lhs))[0]; let expected = [ - new CallShort("Ecmascript.Intrinsics.shl2Dyn", lhs) + new CallShort("Ecmascript.Intrinsics.ecma.shl2dyn", lhs) ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("test expander restores acc", function() { + it("test expander restores acc", function () { class FakeDyn extends Intrinsic { constructor(vs: VReg) { super( @@ -79,13 +79,13 @@ describe("InstructionExpanderTest", function() { expect(checkInstructions(insns, expected)).to.be.true; }); - it("test expander for And2Dyn", function() { + it("test expander for EcmaAnd2dyn", function () { let expander = new IntrinsicExpanderInternal(); let v1 = new VReg(); - let insns = expander.expandInstruction(new And2Dyn(v1))[0]; + let insns = expander.expandInstruction(new EcmaAnd2dyn(v1))[0]; let lhs = new VReg(); let expected = [ - new CallShort("Ecmascript.Intrinsics.and2Dyn", lhs) + new CallShort("Ecmascript.Intrinsics.ecma.and2dyn", lhs) ]; expect(checkInstructions(insns, expected)).to.be.true; }) diff --git a/ts2panda/tests/lexenv.test.ts b/ts2panda/tests/lexenv.test.ts index 19c42f89ab..634973e736 100644 --- a/ts2panda/tests/lexenv.test.ts +++ b/ts2panda/tests/lexenv.test.ts @@ -20,26 +20,28 @@ import { CompilerDriver } from "../src/compilerDriver"; import { - Add2Dyn, - DefinefuncDyn, + EcmaAdd2dyn, + EcmaDefinefuncdyn, + EcmaIncdyn, + EcmaLdlexenvdyn, + EcmaLdlexvardyn, + EcmaNewlexenvdyn, + EcmaReturnundefined, + EcmaStglobalvar, + EcmaStlettoglobalrecord, + EcmaStlexvardyn, + EcmaThrowconstassignment, + EcmaThrowundefinedifhole, + EcmaTonumber, + EcmaTrystglobalbyname, Imm, - IncDyn, IRNode, LdaDyn, LdaiDyn, LdaStr, - LdLexEnv, - LdLexVar, - NewLexEnv, ResultType, ReturnDyn, - ReturnUndefined, StaDyn, - StGlobalVar, - StLexVar, - ThrowConstAssignment, - ThrowUndefinedIfHole, - Tonumber, VReg } from "../src/irnodes"; import { PandaGen } from "../src/pandagen"; @@ -66,9 +68,9 @@ function MicroCreateLexEnv(numVars: number, hasLexEnv: boolean): IRNode[] { let insns = []; if (hasLexEnv) { - insns.push(new NewLexEnv(new Imm(ResultType.Int, numVars))); + insns.push(new EcmaNewlexenvdyn(new Imm(ResultType.Int, numVars))); } else { - insns.push(new LdLexEnv()); + insns.push(new EcmaLdlexenvdyn()); } insns.push(new StaDyn(new VReg())); // create lexenv @@ -79,16 +81,16 @@ function MicroStoreLexVar(level: number, slot: number, kind?: VarDeclarationKind let insns = []; if (kind && name) { - insns.push(new LdLexVar(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot))); + insns.push(new EcmaLdlexvardyn(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot))); insns.push(new StaDyn(new VReg())); insns.push(new LdaStr(name)); insns.push(new StaDyn(new VReg())); - insns.push(new ThrowUndefinedIfHole(new VReg(), new VReg())); + insns.push(new EcmaThrowundefinedifhole(new VReg(), new VReg())); if (kind == VarDeclarationKind.CONST) { - insns.push(new ThrowConstAssignment(new VReg())); + insns.push(new EcmaThrowconstassignment(new VReg())); } } - insns.push(new StLexVar(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot), new VReg())); + insns.push(new EcmaStlexvardyn(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot), new VReg())); insns.push(new LdaDyn(new VReg())); return insns; @@ -97,21 +99,21 @@ function MicroStoreLexVar(level: number, slot: number, kind?: VarDeclarationKind function MicroLoadLexVar(level: number, slot: number, kind?: VarDeclarationKind, name?: string): IRNode[] { let insns = []; - insns.push(new LdLexVar(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot))); + insns.push(new EcmaLdlexvardyn(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot))); if (kind && name) { insns.push(new StaDyn(new VReg())); insns.push(new LdaStr(name)); insns.push(new StaDyn(new VReg())); - insns.push(new ThrowUndefinedIfHole(new VReg(), new VReg())); + insns.push(new EcmaThrowundefinedifhole(new VReg(), new VReg())); insns.push(new LdaDyn(new VReg())); } return insns; } -describe("lexenv-compile-testcase in lexenv.test.ts", function() { +describe("lexenv-compile-testcase in lexenv.test.ts", function () { - it("test CompilerDriver.scanFunctions-with-empty", function() { + it("test CompilerDriver.scanFunctions-with-empty", function () { let source: string = ``; let sourceFile = creatAstFromSnippet(source); let compilerDriver = new CompilerDriver('UnitTest'); @@ -126,7 +128,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(globalScope.getBindingNode() == sourceFile, "functionblock.node should equal to sourceFile").to.be.true; }); - it("test CompilerDriver.scanFunctions-with-embedded-function", function() { + it("test CompilerDriver.scanFunctions-with-embedded-function", function () { let source: string = ` { function outer() { @@ -185,7 +187,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(bindingNodeOfSon1.kind, "son1's parent should equal root!").deep.equal(ts.SyntaxKind.FunctionExpression); }); - it("test CompilerDriver.postorderanalysis-with-empty", function() { + it("test CompilerDriver.postorderanalysis-with-empty", function () { let source: string = ` `; let sourceFile = creatAstFromSnippet(source); @@ -200,7 +202,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(postOrderVariableScopes[0]).to.be.deep.equal(globalScope); }); - it("test CompilerDriver.postorderanalysis-with-embeded-function", function() { + it("test CompilerDriver.postorderanalysis-with-embeded-function", function () { let source: string = ` { function outer() { @@ -252,7 +254,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { * | 4 | | 5 | * +-------+ +------+ */ - it("test CompilerDriver.postorderanalysis-with-IIFE", function() { + it("test CompilerDriver.postorderanalysis-with-IIFE", function () { let source: string = ` (function (global, factory) { // 1 } (this, (function () { 'use strict'; // 2 @@ -285,7 +287,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(postOrderVariableScopes[5]).to.be.deep.equal(globalScope); }); - it("test loadAccFromLexEnv with loacal variable", function() { + it("test loadAccFromLexEnv with loacal variable", function () { let globalScope = new GlobalScope(); let pandaGen = new PandaGen("lexVarPassPandaGen", 1, globalScope); let var1 = globalScope.add("var1", VarDeclarationKind.LET); @@ -307,7 +309,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(checkInstructions(outInsns, expected)).to.be.true; }); - it("test loadAccFromLexEnv with lex env variable", function() { + it("test loadAccFromLexEnv with lex env variable", function () { let globalScope = new GlobalScope(); let pandaGen = new PandaGen("lexVarPassPandaGen", 1, globalScope); let var1 = globalScope.add("var1", VarDeclarationKind.LET); @@ -323,17 +325,17 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { let tempReg = new VReg(); let nameReg = new VReg(); let expected = [ - new LdLexVar(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0)), + new EcmaLdlexvardyn(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0)), new StaDyn(tempReg), new LdaStr("var1"), new StaDyn(nameReg), - new ThrowUndefinedIfHole(new VReg(), nameReg), + new EcmaThrowundefinedifhole(new VReg(), nameReg), new LdaDyn(tempReg) ]; expect(checkInstructions(outInsns, expected)).to.be.true; }); - it("test storeAccFromLexEnv with local variable", function() { + it("test storeAccFromLexEnv with local variable", function () { let globalScope = new GlobalScope(); let pandaGen = new PandaGen("lexVarPassPandaGen", 1, globalScope); let var1 = globalScope.add("var1", VarDeclarationKind.LET); @@ -352,7 +354,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { expect(checkInstructions(outInsns, expected)).to.be.true; }); - it("test storeAccFromLexEnv with lex env let-variable", function() { + it("test storeAccFromLexEnv with lex env let-variable", function () { let globalScope = new GlobalScope(); let pandaGen = new PandaGen("lexVarPassPandaGen", 1, globalScope); let var1 = globalScope.add("var1", VarDeclarationKind.LET); @@ -369,13 +371,13 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { let valueReg = new VReg(); let expected = [ new StaDyn(valueReg), - new StLexVar(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0), valueReg), + new EcmaStlexvardyn(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0), valueReg), new LdaDyn(new VReg()) ]; expect(checkInstructions(outInsns, expected)).to.be.true; }); - it("test storeAccFromLexEnv with lex env const-variable", function() { + it("test storeAccFromLexEnv with lex env const-variable", function () { let globalScope = new GlobalScope(); let pandaGen = new PandaGen("lexVarPassPandaGen", 1, globalScope); let var1 = globalScope.add("var1", VarDeclarationKind.CONST); @@ -391,13 +393,13 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { let valueReg = new VReg(); let expected = [ new StaDyn(valueReg), - new StLexVar(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0), valueReg), + new EcmaStlexvardyn(new Imm(ResultType.Int, 0), new Imm(ResultType.Int, 0), valueReg), new LdaDyn(valueReg) ]; expect(checkInstructions(outInsns, expected)).to.be.true; }); - it("test lexenv variable capture in function", function() { + it("test lexenv variable capture in function", function () { let source: string = ` var outer = 1; @@ -409,29 +411,29 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { let pandaGens = compileAllSnippet(source); let expected_main = [ new LdaDyn(new VReg()), - new StGlobalVar("outer"), - new DefinefuncDyn("func_func_1", new VReg()), - new StGlobalVar("func"), + new EcmaStglobalvar("outer"), + new EcmaDefinefuncdyn("func", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("func"), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StGlobalVar("outer"), - new ReturnUndefined() + new EcmaStglobalvar("outer"), + new EcmaReturnundefined() ]; let expected_func = [ new LdaiDyn(new Imm(ResultType.Int, 2)), - new StGlobalVar("outer"), - new ReturnUndefined() + new EcmaStglobalvar("outer"), + new EcmaReturnundefined() ]; pandaGens.forEach((pg) => { if (pg.internalName == "func_main_0") { expect(checkInstructions(pg.getInsns(), expected_main)).to.be.true; - } else if (pg.internalName == "func_func_1") { + } else if (pg.internalName == "func") { expect(checkInstructions(pg.getInsns(), expected_func)).to.be.true; } }) }); - it("test lexenv let capture in function", function() { + it("test lexenv let capture in function", function () { let source: string = ` let outer = 1; @@ -440,45 +442,44 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { } `; - let insnsCreateLexEnv_main = MicroCreateLexEnv(1, true); - let insnsStoreLexVar_main = MicroStoreLexVar(0, 0); + let insnsCreateLexEnv_main = MicroCreateLexEnv(1, false); let passes = [new CacheExpander()]; let pandaGens = compileAllSnippet(source, passes); let expected_main = [ ...insnsCreateLexEnv_main, - new DefinefuncDyn("func_func_1", new VReg()), - new StGlobalVar("func"), // global.func = func_func_1 + new EcmaDefinefuncdyn("func", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("func"), // global.func = func_func_1 new LdaiDyn(new Imm(ResultType.Int, 1)), // value = 1 - new StaDyn(new VReg()), - ...insnsStoreLexVar_main, - new ReturnUndefined() + // ...insnsStoreLexVar_main, + new EcmaStlettoglobalrecord("outer"), + new EcmaReturnundefined() ]; - let insnsStoreLexVar_func = MicroStoreLexVar(1, 0, VarDeclarationKind.LET, "outer"); - let insnsCreateLexEnv_func = MicroCreateLexEnv(0, true); + let insnsCreateLexEnv_func = MicroCreateLexEnv(0, false); let expected_func = [ ...insnsCreateLexEnv_func, new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(new VReg()), - ...insnsStoreLexVar_func, - new ReturnUndefined() + // ...insnsStoreLexVar_func, + new EcmaTrystglobalbyname("outer"), + new EcmaReturnundefined() ]; pandaGens.forEach((pg) => { let scope = pg.getScope(); if (pg.internalName == "func_main_0") { expect(checkInstructions(pg.getInsns(), expected_main), "check main insns").to.be.true; - expect(scope.getNumLexEnv(), "main scope has 1 lexvar").to.be.equal(1); - expect(scope.hasLexEnv(), "main scope has lexenv").to.be.true; - } else if (pg.internalName == "func_func_1") { + expect(scope.getNumLexEnv(), "main scope has 0 lexvar").to.be.equal(0); + // expect(scope.hasLexEnv(), "main scope has lexenv").to.be.true; + } else if (pg.internalName == "func") { + expect(checkInstructions(pg.getInsns(), expected_func), "check func insns").to.be.true; expect(scope.getNumLexEnv(), "func scope has 1 lexvar").to.be.equal(0); - expect(scope.hasLexEnv(), "func scope has lexenv").to.be.true; + // expect(scope.hasLexEnv(), "func scope has lexenv").to.be.true; } }); }); - it("test lexenv capture in function", function() { + it("test lexenv capture in function", function () { let source: string = ` var a = 1; function outer(a, b) { @@ -504,7 +505,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { new LdaDyn(new VReg()), new StaDyn(new VReg()), ...insnsStoreLexVar_outer_2, - new DefinefuncDyn("func_2", new VReg()), + new EcmaDefinefuncdyn("#2#", new Imm(ResultType.Int, 0), new VReg()), // returnStatement new StaDyn(new VReg()), new LdaDyn(new VReg()), @@ -516,14 +517,14 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { ...MicroCreateLexEnv(0, true), ...MicroLoadLexVar(1, 0), new StaDyn(new VReg()), - new IncDyn(new VReg()), + new EcmaIncdyn(new VReg()), new StaDyn(new VReg()), ...MicroStoreLexVar(1, 0), - new Tonumber(new VReg()), // this is reduntant load varialbe + new EcmaTonumber(new VReg()), // this is reduntant load varialbe ...MicroLoadLexVar(1, 0), new StaDyn(new VReg), ...MicroLoadLexVar(1, 1), - new Add2Dyn(new VReg()), + new EcmaAdd2dyn(new VReg()), // returnStatement new StaDyn(new VReg()), new LdaDyn(new VReg()), @@ -535,20 +536,20 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function() { snippetCompiler.compile(source, passes); // check compile result! - let outerPg = snippetCompiler.getPandaGenByName("func_outer_1"); + let outerPg = snippetCompiler.getPandaGenByName("outer"); let outerScope = outerPg!.getScope(); let outerA = outerScope!.findLocal("a"); expect(outerA instanceof LocalVariable, "a in outer is local variable").to.be.true; - expect((outerScope).hasLexEnv(), "outer scope need to create lex env").to.be.true; + // expect((outerScope).hasLexEnv(), "outer scope need to create lex env").to.be.true; expect((outerScope).getNumLexEnv(), "number of lexvar at outer scope").to.be.equal(2); - let anonymousPg = snippetCompiler.getPandaGenByName("func_2"); + let anonymousPg = snippetCompiler.getPandaGenByName("#2#"); let anonymousScope = anonymousPg!.getScope(); let anonymousA = anonymousScope!.findLocal("a"); let searchRlt = anonymousScope!.find("a"); expect(searchRlt!.level).to.be.equal(1); expect(searchRlt!.scope, "a is defined in outerscope").to.be.deep.equal(outerScope); expect(anonymousA, "no a in anonymous function").to.be.undefined; - expect((anonymousScope).hasLexEnv(), "anonymous scope had lex env").to.be.true; + // expect((anonymousScope).hasLexEnv(), "anonymous scope had lex env").to.be.true; expect((anonymousScope).getNumLexEnv()).to.be.equal(0); let globalPg = snippetCompiler.getPandaGenByName("func_main_0"); let globalScope = globalPg!.getScope(); diff --git a/ts2panda/tests/pandagen.test.ts b/ts2panda/tests/pandagen.test.ts index f96187ca58..c380eeb24e 100644 --- a/ts2panda/tests/pandagen.test.ts +++ b/ts2panda/tests/pandagen.test.ts @@ -13,11 +13,11 @@ * limitations under the License. */ -import * as ts from "typescript"; import { expect } from 'chai'; import 'mocha'; +import * as ts from "typescript"; import { StaDyn, VReg @@ -25,8 +25,8 @@ import { import { PandaGen } from "../src/pandagen"; import { checkInstructions } from "./utils/base"; -describe("PandaGenTest", function() { - it("StoreAccumulator", function() { +describe("PandaGenTest", function () { + it("StoreAccumulator", function () { let pandaGen = new PandaGen("pandaGen", 0); let vreg = new VReg(); pandaGen.storeAccumulator(ts.createNode(0), vreg); diff --git a/ts2panda/tests/regAllocator.test.ts b/ts2panda/tests/regAllocator.test.ts index 0a35621cf6..93e4c6892f 100644 --- a/ts2panda/tests/regAllocator.test.ts +++ b/ts2panda/tests/regAllocator.test.ts @@ -17,21 +17,20 @@ import { expect } from 'chai'; import 'mocha'; import * as ts from "typescript"; import { - BuiltinAcc, - BuiltinR2i, CallRange, + EcmaCallirangedyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, Imm, IRNode, - LdaDyn, - MovDyn, + LdaiDyn, ResultType, - ReturnUndefined, StaDyn, VReg } from "../src/irnodes"; import { PandaGen } from "../src/pandagen"; import { CacheExpander } from "../src/pass/cacheExpander"; -import { IntrinsicVariantExpander } from "../src/pass/intrinsicVariantExpander"; import { RegAlloc } from "../src/regAllocator"; import { basicChecker, checkInstructions, compileAllSnippet } from "./utils/base"; @@ -56,8 +55,8 @@ function checkRegisterNumber(left: IRNode, right: IRNode): boolean { } return true; } -describe("RegAllocator", function() { - it("make spill for Src register", function() { +describe("RegAllocator", function () { + it("make spill for Src register", function () { let string: string = ""; for (let i = 0; i < 256; ++i) { string += "let a" + i + " = " + i + ";"; @@ -66,31 +65,24 @@ describe("RegAllocator", function() { let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]); let insns = pgs[0].getInsns(); - let v260 = new VReg(); - v260.num = 260; - let v259 = new VReg(); - v259.num = 259; - let v258 = new VReg(); - v258.num = 258; - let v0 = new VReg(); - v0.num = 0; let expected: IRNode[] = [ - new MovDyn(v260, v0), - new StaDyn(v0), - new MovDyn(v258, v0), - new MovDyn(v0, v260), - - new MovDyn(v260, v0), - new MovDyn(v0, v258), - new LdaDyn(v0), - new MovDyn(v0, v260), - new ReturnUndefined() - ]; - expect(checkInstructions(insns.slice(insns.length - 9), expected, checkRegisterNumber)).to.be.true; + new LdaiDyn(new Imm(ResultType.Int, 252)), + new EcmaStlettoglobalrecord('a252'), + new LdaiDyn(new Imm(ResultType.Int, 253)), + new EcmaStlettoglobalrecord('a253'), + new LdaiDyn(new Imm(ResultType.Int, 254)), + new EcmaStlettoglobalrecord('a254'), + new LdaiDyn(new Imm(ResultType.Int, 255)), + new EcmaStlettoglobalrecord('a255'), + new EcmaTryldglobalbyname('a255'), + new EcmaReturnundefined() + ] + + expect(checkInstructions(insns.slice(insns.length - 10), expected, checkRegisterNumber)).to.be.true; }); - it("make spill for SrcDst register", function() { + it("make spill for SrcDst register", function () { /* the only possible instruction whose operand register type could be SrcDstVReg is INCI, * but we do not use it at all by now */ @@ -107,40 +99,39 @@ describe("RegAllocator", function() { string += "let a" + i + " = " + i + ";"; } string += "call(a252, a253, a254, a255);"; - let pgs = compileAllSnippet(string, [new CacheExpander(), new IntrinsicVariantExpander(), new RegAlloc()]); + let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]); let insns = pgs[0].getInsns(); let v = []; - for (let i = 0; i < 5; ++i) { - v[i] = new VReg(); - v[i].num = i; - } - for (let i = 259; i <= 269; ++i) { + for (let i = 0; i < 8; ++i) { v[i] = new VReg(); v[i].num = i; } let expected = [ - new MovDyn(v[265], v[0]), - new MovDyn(v[0], v[259]), - new MovDyn(v[266], v[1]), - new MovDyn(v[1], v[260]), - new MovDyn(v[267], v[2]), - new MovDyn(v[2], v[261]), - new MovDyn(v[268], v[3]), - new MovDyn(v[3], v[262]), - new MovDyn(v[269], v[4]), - new MovDyn(v[4], v[263]), - new BuiltinR2i(new Imm(ResultType.Int, 3), new Imm(ResultType.Int, 4), v.slice(0, 5)), - new MovDyn(v[0], v[265]), - new MovDyn(v[1], v[266]), - new MovDyn(v[2], v[267]), - new MovDyn(v[3], v[268]), - new MovDyn(v[4], v[269]), - new BuiltinAcc(new Imm(ResultType.Int, 23)) // ReturnUndefined + new LdaiDyn(new Imm(ResultType.Int, 252)), + new EcmaStlettoglobalrecord('a252'), + new LdaiDyn(new Imm(ResultType.Int, 253)), + new EcmaStlettoglobalrecord('a253'), + new LdaiDyn(new Imm(ResultType.Int, 254)), + new EcmaStlettoglobalrecord('a254'), + new LdaiDyn(new Imm(ResultType.Int, 255)), + new EcmaStlettoglobalrecord('a255'), + new EcmaTryldglobalbyname('call'), + new StaDyn(v[3]), + new EcmaTryldglobalbyname('a252'), + new StaDyn(v[4]), + new EcmaTryldglobalbyname('a253'), + new StaDyn(v[5]), + new EcmaTryldglobalbyname('a254'), + new StaDyn(v[6]), + new EcmaTryldglobalbyname('a255'), + new StaDyn(v[7]), + new EcmaCallirangedyn(new Imm(ResultType.Int, 4), [v[3],v[4],v[5],v[6],v[7]]), + new EcmaReturnundefined(), ]; - expect(checkInstructions(insns.slice(insns.length - 17), expected, checkRegisterNumber)).to.be.true; + expect(checkInstructions(insns.slice(insns.length - 20), expected, checkRegisterNumber)).to.be.true; }); - it("VReg sequence of CalliDynRange is not continuous", function() { + it("VReg sequence of CalliDynRange is not continuous", function () { let pandaGen = new PandaGen('', 0); let para1 = pandaGen.getTemp(); @@ -163,7 +154,7 @@ describe("RegAllocator", function() { expect(true).to.be.false; }); - it("VReg sequence of DynRange is not continuous", function() { + it("VReg sequence of DynRange is not continuous", function () { let pandaGen = new PandaGen('', 0); let para1 = pandaGen.getTemp(); diff --git a/ts2panda/tests/scope.test.ts b/ts2panda/tests/scope.test.ts index 3b2a4dde10..85ef72aa12 100644 --- a/ts2panda/tests/scope.test.ts +++ b/ts2panda/tests/scope.test.ts @@ -28,8 +28,8 @@ import { VarDeclarationKind } from "../src/variable"; -describe("ScopeTest", function() { - it("test add 'none' variable to GlobalScope", function() { +describe("ScopeTest", function () { + it("test add 'none' variable to GlobalScope", function () { let scope = new GlobalScope(); let variable = scope.add("x", VarDeclarationKind.NONE); expect(variable instanceof GlobalVariable).to.be.true; @@ -39,7 +39,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add 'var' variable to GlobalScope", function() { + it("test add 'var' variable to GlobalScope", function () { let scope = new GlobalScope(); let variable = scope.add("x", VarDeclarationKind.VAR); expect(variable instanceof GlobalVariable).to.be.true; @@ -49,7 +49,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add 'let' variable to GlobalScope", function() { + it("test add 'let' variable to GlobalScope", function () { let scope = new GlobalScope(); let variable = scope.add("x", VarDeclarationKind.LET); expect(variable instanceof LocalVariable).to.be.true; @@ -59,7 +59,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add 'const' variable to GlobalScope", function() { + it("test add 'const' variable to GlobalScope", function () { let scope = new GlobalScope(); let variable = scope.add("x", VarDeclarationKind.CONST); expect(variable instanceof LocalVariable).to.be.true; @@ -69,14 +69,14 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add several variables to GlobalScope", function() { + it("test add several variables to GlobalScope", function () { let scope = new GlobalScope(); let x = scope.add("x", VarDeclarationKind.LET); let y = scope.add("y", VarDeclarationKind.NONE); let z = scope.add("z", VarDeclarationKind.LET); }); - it("test add 'none' variable to FunctionScope", function() { + it("test add 'none' variable to FunctionScope", function () { let globalScope = new GlobalScope(); let scope = new FunctionScope(globalScope); let variable = scope.add("x", VarDeclarationKind.NONE); @@ -87,7 +87,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(globalScope); }); - it("test add 'var' variable to FunctionScope", function() { + it("test add 'var' variable to FunctionScope", function () { let scope = new FunctionScope(); let variable = scope.add("x", VarDeclarationKind.VAR); expect(variable instanceof LocalVariable).to.be.true; @@ -97,7 +97,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add 'let' variable to FunctionScope", function() { + it("test add 'let' variable to FunctionScope", function () { let scope = new FunctionScope(); let variable = scope.add("x", VarDeclarationKind.LET); expect(variable instanceof LocalVariable).to.be.true; @@ -107,7 +107,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add 'const' variable to FunctionScope", function() { + it("test add 'const' variable to FunctionScope", function () { let scope = new FunctionScope(); let variable = scope.add("x", VarDeclarationKind.LET); expect(variable instanceof LocalVariable).to.be.true; @@ -117,7 +117,7 @@ describe("ScopeTest", function() { expect(sp).to.be.equal(scope); }); - it("test add several variables to FunctionScope", function() { + it("test add several variables to FunctionScope", function () { let globalScope = new GlobalScope(); let scope = new FunctionScope(globalScope); let x = scope.add("x", VarDeclarationKind.LET); @@ -125,7 +125,7 @@ describe("ScopeTest", function() { let z = scope.add("z", VarDeclarationKind.LET); }); - it("test add 'none' variable to LocalScope", function() { + it("test add 'none' variable to LocalScope", function () { let parent = new FunctionScope(); let scope = new LocalScope(parent); let variable = scope.add("x", VarDeclarationKind.NONE); @@ -140,7 +140,7 @@ describe("ScopeTest", function() { expect(spParent).to.be.equal(undefined); }); - it("test add 'var' variable to LocalScope", function() { + it("test add 'var' variable to LocalScope", function () { let parent = new FunctionScope(); let scope = new LocalScope(parent); let variable = scope.add("x", VarDeclarationKind.VAR); @@ -155,7 +155,7 @@ describe("ScopeTest", function() { expect(spParent).to.be.equal(parent); }); - it("test add 'let' variable to LocalScope", function() { + it("test add 'let' variable to LocalScope", function () { let parent = new FunctionScope(); let scope = new LocalScope(parent); let variable = scope.add("x", VarDeclarationKind.LET); @@ -168,7 +168,7 @@ describe("ScopeTest", function() { expect(outVariableParent === undefined).to.be.true; }); - it("test add 'const' variable to LocalScope", function() { + it("test add 'const' variable to LocalScope", function () { let parent = new FunctionScope(); let scope = new LocalScope(parent); let variable = scope.add("x", VarDeclarationKind.LET); @@ -181,7 +181,7 @@ describe("ScopeTest", function() { expect(outVariableParent === undefined).to.be.true; }); - it("test add several variables to LocalScope", function() { + it("test add several variables to LocalScope", function () { let global = new GlobalScope(); let parent = new FunctionScope(global); let scope = new LocalScope(parent); @@ -216,7 +216,7 @@ describe("ScopeTest", function() { * | func4 | * +---------+ */ - it("test multi-scope nesting function", function() { + it("test multi-scope nesting function", function () { let globalScope = new GlobalScope(); let func1Scope = new FunctionScope(globalScope); let aV = func1Scope.add("a", VarDeclarationKind.LET); @@ -246,24 +246,24 @@ describe("ScopeTest", function() { expect(p2FindEntry.scope).to.be.equal(func1Scope); // check global - expect(globalScope.hasLexEnv(), "gloal has lexenv").to.be.false; + // expect(globalScope.hasLexEnv(), "gloal has lexenv").to.be.false; // check func1 - expect(func1Scope.hasLexEnv(), "func1 haslexenv").to.be.true; + // expect(func1Scope.hasLexEnv(), "func1 haslexenv").to.be.true; expect(func1Scope.getNumLexEnv(), "func1 status").to.be.equal(2); // check fun21 - expect(func21Scope.hasLexEnv(), "func21 has lexenv").to.be.true; + // expect(func21Scope.hasLexEnv(), "func21 has lexenv").to.be.true; expect(func21Scope.getNumLexEnv(), "func21 status").to.be.equal(0); // check fun22 - expect(func22Scope.hasLexEnv(), "func22 has lexenv").to.be.true; + // expect(func22Scope.hasLexEnv(), "func22 has lexenv").to.be.true; expect(func22Scope.getNumLexEnv(), "func22 status").to.be.equal(0); // check fun31 - expect(func31Scope.hasLexEnv(), "func31 has lexenv").to.be.false; + // expect(func31Scope.hasLexEnv(), "func31 has lexenv").to.be.false; expect(func31Scope.getNumLexEnv(), "func31 status").to.be.equal(0); // check fun32 - expect(func32Scope.hasLexEnv(), "func32 has lexenv").to.be.true; + // expect(func32Scope.hasLexEnv(), "func32 has lexenv").to.be.true; expect(func32Scope.getNumLexEnv(), "func32 status").to.be.equal(0); // check fun4 - expect(func4Scope.hasLexEnv(), "func4 has lexenv").to.be.false; + // expect(func4Scope.hasLexEnv(), "func4 has lexenv").to.be.false; expect(func4Scope.getNumLexEnv(), "func4 status").to.be.equal(0); }); }) diff --git a/ts2panda/tests/otherStatements.test.ts b/ts2panda/tests/statements/debugger.test.ts similarity index 74% rename from ts2panda/tests/otherStatements.test.ts rename to ts2panda/tests/statements/debugger.test.ts index f121dce9cb..9cbe527f94 100644 --- a/ts2panda/tests/otherStatements.test.ts +++ b/ts2panda/tests/statements/debugger.test.ts @@ -18,17 +18,17 @@ import { } from 'chai'; import 'mocha'; import { - Debugger, - ReturnUndefined -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; + EcmaDebugger, + EcmaReturnundefined +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("DebuggerTest", function() { - it("debugger", function() { +describe("DebuggerTest", function () { + it("debugger", function () { let insns = compileMainSnippet("debugger;"); let expected = [ - new Debugger(), - new ReturnUndefined() + new EcmaDebugger(), + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/statements/doWhile.test.ts b/ts2panda/tests/statements/doWhile.test.ts new file mode 100644 index 0000000000..ca308a2d4a --- /dev/null +++ b/ts2panda/tests/statements/doWhile.test.ts @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaLessdyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + Imm, + Jeqz, + Jmp, + Label, LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + + +describe("DoWhileLoopTest", function () { + it('doWhileLoopEmpty', function () { + let insns = compileMainSnippet("do {} while (true)"); + + let jumps = insns.filter(item => item instanceof Jmp); + + expect(jumps.length).to.equal(1); + + let jmpLabel = (jumps[0]).getTarget(); + + expect(jmpLabel).to.equal(insns[0]); + }); + + it('doWhileLoopWithBody', function () { + let insns = compileMainSnippet("let a = 5;" + + "do { a++ } while (a < 11);"); + + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(2); + + let jgezLabel = (jumps[0]).getTarget(); + let jmpLabel = (jumps[1]).getTarget(); + + expect(jmpLabel).to.equal(insns[2]); + expect(jgezLabel).to.equal(insns[15]); + + expect(insns[13]).to.equal(jumps[0]); + expect(insns[14]).to.equal(jumps[1]); + }); + + it('doWhileLoopWithContinue', function () { + let insns = compileMainSnippet("let a = 5;" + + "do { a = 1; continue; } while (a < 1);"); + let a = new VReg(); + let lhs = new VReg(); + let labelPre = new Label(); + let labelCond = new Label(); + let labelPost = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + // body + labelPre, + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaTrystglobalbyname('a'), + new Jmp(labelCond), // continue + // condition + labelCond, + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ] + + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[5]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[6]); + }); + + it('doWhileLoopWithBreak', function () { + let insns = compileMainSnippet("let a = 5;" + + "do { a = 1; break; } while (a < 1);"); + let a = new VReg(); + let lhs = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let labelCond = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + //body + labelPre, + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaTrystglobalbyname('a'), + new Jmp(labelPost), // break + // condition + labelCond, + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ] + + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[5]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[13]); + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/loops.test.ts b/ts2panda/tests/statements/for.test.ts similarity index 33% rename from ts2panda/tests/loops.test.ts rename to ts2panda/tests/statements/for.test.ts index 7f5bc717ba..6b52e9cfd5 100644 --- a/ts2panda/tests/loops.test.ts +++ b/ts2panda/tests/statements/for.test.ts @@ -1,869 +1,325 @@ -/* - * Copyright (c) 2021 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 { - expect -} from 'chai'; -import 'mocha'; -import { - Add2Dyn, - CalliThisRangeDyn, - CreateEmptyArray, - EqDyn, - GetIterator, - Imm, - IncDyn, - Jeqz, - Jgez, - Jmp, - Label, - LdaDyn, - LdaiDyn, - LdObjByName, - LdTrue, - LessDyn, - ResultType, - ReturnUndefined, - StaDyn, - StrictNotEqDyn, - ThrowDyn, - ThrowIfNotObject, - Toboolean, - Tonumber, - VReg -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; -import { DiagnosticCode } from '../src/diagnostic'; - -describe("ForLoopTest", function() { - it('forLoopEmpty', function() { - let insns = compileMainSnippet("for (;;) {}"); - let labelPre = new Label(); - let labelPost = new Label(); - let labelIncr = new Label(); - let expected = [ - labelPre, - labelIncr, - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ]; - let jumps = insns.filter(item => item instanceof Jmp); - - expect(jumps.length).to.equal(1); - - let jmpLabel = (jumps[0]).getTarget(); - - expect(checkInstructions(insns, expected)).to.be.true; - expect(jmpLabel).to.equal(insns[0]); - }); - - it('forLoopWithInitializer', function() { - let insns = compileMainSnippet("for (let i = 0;;) {}"); - let jumps = insns.filter(item => item instanceof Jmp); - - expect(jumps.length).to.equal(1); - - let jmpLabel = (jumps[0]).getTarget(); - - expect(insns[4]).to.equal(jumps[0]); - expect(jmpLabel).to.equal(insns[2]); - }); - - it('forLoopWithInitializerAndCondition', function() { - let insns = compileMainSnippet("for (let i = 0; i < 5;) {}"); - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(2); - - let jgezLabel = (jumps[0]).getTarget(); - let jmpLabel = (jumps[1]).getTarget(); - - expect(jmpLabel).to.equal(insns[2]); - expect(jgezLabel).to.equal(insns[10]); - - expect(insns[7]).to.equal(jumps[0]); - expect(insns[9]).to.equal(jumps[1]); - }); - - it('forLoopWithInitializerAndConditionAndIncrementor', function() { - let insns = compileMainSnippet("for (let i = 0; i < 5; i++) {}"); - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(2); - - let jgezLabel = (jumps[0]).getTarget(); - let jmpLabel = (jumps[1]).getTarget(); - - expect(jmpLabel).to.equal(insns[2]); - expect(jgezLabel).to.equal(insns[15]); - - expect(insns[7]).to.equal(jumps[0]); - expect(insns[14]).to.equal(jumps[1]); - }); - - it('forLoopWithContinue', function() { - let insns = compileMainSnippet("for (let i = 0; i < 5; ++i) { continue; }"); - let i = new VReg(); - let lhs = new VReg(); - let operand = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let labelIncr = new Label(); - let expected = [ - // initializer - new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(i), - labelPre, - // condition - new LdaDyn(i), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 5)), - new LessDyn(lhs), - new Jeqz(labelPost), - // body - new Jmp(labelIncr), // continue - labelIncr, - // incrementor - new LdaDyn(i), - new StaDyn(operand), - new IncDyn(operand), - new StaDyn(i), - // jump to the loop header - new Jmp(new Label()), - labelPost, - new ReturnUndefined() - ]; - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[8]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[9]); - }); - - it('forLoopWithBreak', function() { - let insns = compileMainSnippet("for (let i = 0; i < 5; ++i) {break; }"); - let i = new VReg(); - let lhs = new VReg(); - let operand = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let labelIncr = new Label(); - let expected = [ - // initializer - new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(i), - labelPre, - // condition - new LdaDyn(i), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 5)), - new LessDyn(lhs), - new Jeqz(labelPost), - // body - new Jmp(labelPost), // break - // incrementor - labelIncr, - new LdaDyn(i), - new StaDyn(operand), - new IncDyn(operand), - new StaDyn(i), - // jump to the loop header - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ]; - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[8]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[15]); - }); -}); - -describe("ForOfLoopTest", function() { - it("forOfLoopWithEmptyArray", function() { - let insns = compileMainSnippet("for (let a of []) {}"); - let a = new VReg(); - let arrInstance = new VReg(); - let iterReg = new VReg(); - let nextMethodReg = new VReg(); - let resultObj = new VReg(); - let exceptionVreg = new VReg(); - let trueReg = new VReg(); - let done = new VReg(); - let value = new VReg(); - - let loopStartLabel = new Label(); - let loopEndLabel = new Label(); - let tryBeginLabel = new Label(); - let tryEndLabel = new Label(); - let catchBeginLabel = new Label(); - let isDone = new Label(); - - let expected = [ - new CreateEmptyArray(), - new StaDyn(arrInstance), - new GetIterator(), - new StaDyn(iterReg), - new LdObjByName("next", iterReg), - new StaDyn(nextMethodReg), - - new LdaDyn(new VReg()), - new StaDyn(done), - - tryBeginLabel, - new LdaDyn(trueReg), - new StaDyn(done), - loopStartLabel, - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - new StaDyn(resultObj), - new ThrowIfNotObject(resultObj), - new LdObjByName("done", resultObj), - new Toboolean(), - new StrictNotEqDyn(trueReg), - new Jeqz(loopEndLabel), - new LdObjByName("value", resultObj), - new StaDyn(value), - - new LdaDyn(new VReg()), - new StaDyn(done), - - new LdaDyn(value), - new StaDyn(a), - tryEndLabel, - - new Jmp(loopStartLabel), - - catchBeginLabel, - new StaDyn(exceptionVreg), - new LdaDyn(done), - new StrictNotEqDyn(trueReg), - new Jeqz(isDone), - new LdObjByName("return", iterReg), - new StaDyn(nextMethodReg), - new StrictNotEqDyn(new VReg()), - new Jeqz(isDone), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - isDone, - new LdaDyn(exceptionVreg), - new ThrowDyn(), - - loopEndLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(4); - }); - - it("forOfLoopWithContinue", function() { - let insns = compileMainSnippet("for (let a of []) {continue;}"); - let a = new VReg(); - let arrInstance = new VReg(); - let resultObj = new VReg(); - let trueReg = new VReg(); - let iterReg = new VReg(); - let exceptionVreg = new VReg(); - let nextMethodReg = new VReg(); - let done = new VReg(); - let value = new VReg(); - - let loopStartLabel = new Label(); - let loopEndLabel = new Label(); - let tryBeginLabel = new Label(); - let tryEndLabel = new Label(); - let catchBeginLabel = new Label(); - let isDone = new Label(); - let insertedtryBeginLabel = new Label(); - let insertedtryEndLabel = new Label(); - - let expected = [ - new CreateEmptyArray(), - new StaDyn(arrInstance), - new GetIterator(), - new StaDyn(iterReg), - new LdObjByName("next", iterReg), - new StaDyn(nextMethodReg), - - new LdaDyn(new VReg()), - new StaDyn(done), - - tryBeginLabel, - new LdaDyn(trueReg), - new StaDyn(done), - loopStartLabel, - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - new StaDyn(resultObj), - new ThrowIfNotObject(resultObj), - new LdObjByName("done", resultObj), - new Toboolean(), - new StrictNotEqDyn(trueReg), - new Jeqz(loopEndLabel), - new LdObjByName("value", resultObj), - new StaDyn(value), - - new LdaDyn(new VReg()), - new StaDyn(done), - - new LdaDyn(value), - new StaDyn(a), - - insertedtryBeginLabel, - insertedtryEndLabel, - new Jmp(loopStartLabel), - - tryEndLabel, - - new Jmp(loopStartLabel), - - catchBeginLabel, - new StaDyn(exceptionVreg), - new LdaDyn(done), - new StrictNotEqDyn(trueReg), - new Jeqz(isDone), - new LdObjByName("return", iterReg), - new StaDyn(nextMethodReg), - new StrictNotEqDyn(new VReg()), - new Jeqz(isDone), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - isDone, - new LdaDyn(exceptionVreg), - new ThrowDyn(), - - loopEndLabel, - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(5); - }); - - it("forOfLoopWithBreak", function() { - let insns = compileMainSnippet("for (let a of []) {break;}"); - let a = new VReg(); - let arrInstance = new VReg(); - let resultObj = new VReg(); - let exceptionVreg = new VReg(); - let iterReg = new VReg(); - let trueReg = new VReg(); - let nextMethodReg = new VReg(); - let done = new VReg(); - let value = new VReg(); - let loopStartLabel = new Label(); - let loopEndLabel = new Label(); - let tryBeginLabel = new Label(); - let tryEndLabel = new Label(); - let catchBeginLabel = new Label(); - let isDone = new Label(); - let noReturn = new Label(); - let insertedtryBeginLabel = new Label(); - let insertedtryEndLabel = new Label(); - - let expected = [ - new CreateEmptyArray(), - new StaDyn(arrInstance), - new GetIterator(), - new StaDyn(iterReg), - new LdObjByName("next", iterReg), - new StaDyn(nextMethodReg), - - new LdaDyn(new VReg()), - new StaDyn(done), - - tryBeginLabel, - new LdaDyn(trueReg), - new StaDyn(done), - loopStartLabel, - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - new StaDyn(resultObj), - new ThrowIfNotObject(resultObj), - new LdObjByName("done", resultObj), - new Toboolean(), - new StrictNotEqDyn(trueReg), - new Jeqz(loopEndLabel), - new LdObjByName("value", resultObj), - new StaDyn(value), - - new LdaDyn(new VReg()), - new StaDyn(done), - - new LdaDyn(value), - new StaDyn(a), - - insertedtryBeginLabel, - new LdObjByName("return", iterReg), - new StaDyn(nextMethodReg), - new StrictNotEqDyn(new VReg()), // undefined - new Jeqz(noReturn), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - new StaDyn(new VReg()), - new ThrowIfNotObject(new VReg()), - noReturn, - insertedtryEndLabel, - new Jmp(loopEndLabel), - - tryEndLabel, - - new Jmp(loopStartLabel), - - catchBeginLabel, - new StaDyn(exceptionVreg), - new LdaDyn(done), - new StrictNotEqDyn(trueReg), - new Jeqz(isDone), - new LdObjByName("return", iterReg), - new StaDyn(nextMethodReg), - new StrictNotEqDyn(new VReg()), - new Jeqz(isDone), - new CalliThisRangeDyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), - isDone, - new LdaDyn(exceptionVreg), - new ThrowDyn(), - - loopEndLabel, - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(6); - }); - - it("ForIn SyntaxError", function() { - let source: string = `for ([(x, y)] in {}) { }`; - let errorThrown = false; - try { - compileMainSnippet(source); - } catch (err) { - expect(err.code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected); - errorThrown = true; - } - expect(errorThrown).to.be.true; - }); - - it("ForOf SyntaxError", function() { - let source: string = `for ([(x, y)] of []) {}`; - let errorThrown = false; - try { - compileMainSnippet(source); - } catch (err) { - expect(err.code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected); - errorThrown = true; - } - expect(errorThrown).to.be.true; - }); -}); - -describe("WhileLoopTest", function() { - it("while (true) {}", function() { - let insns = compileMainSnippet("while (true) {}"); - let labelPre = new Label(); - let labelPost = new Label(); - let trueReg = new VReg(); - let expected = [ - labelPre, - new LdaDyn(new VReg()), - new Toboolean(), - new EqDyn(trueReg), - new Jeqz(labelPost), - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("while (a + b) {}", function() { - let insns = compileMainSnippet("let a, b; while (a + b) {}"); - let loopBegin = new Label(); - let loopEnd = new Label(); - let a = new VReg(); - let b = new VReg(); - let lhs = new VReg(); - let trueReg = new VReg(); - let expected = [ - loopBegin, - // a + b - new LdaDyn(a), - new StaDyn(lhs), - new LdaDyn(b), - new Add2Dyn(lhs), - new Toboolean(), - new EqDyn(trueReg), - new Jeqz(loopEnd), - // body - new Jmp(loopBegin), - loopEnd - ]; - - insns = insns.slice(4, insns.length - 1); // skip let a, b and return.dyn - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('whileLoopWithBody', function() { - let insns = compileMainSnippet(` - let a; - while (a < 0) { a = 1; } - `); - - let a = new VReg(); - let lhs = new VReg(); - let loopBegin = new Label(); - let loopEnd = new Label(); - let expected = [ - loopBegin, - // condition - // compute lhs - new LdaDyn(a), - new StaDyn(lhs), - // compute rhs - new LdaiDyn(new Imm(ResultType.Int, 0)), - new LessDyn(lhs), - new Jeqz(loopEnd), - - // body - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), - new Jmp(loopBegin), - - loopEnd, - ]; - - insns = insns.slice(2, insns.length - 1); // skip let a and return.dyn - expect(checkInstructions(insns, expected)).to.be.true; - expect((insns[5]).getTarget() === insns[insns.length - 1]).to.be.true; - expect((insns[insns.length - 2]).getTarget() === insns[0]).to.be.true; - }); - - it('whileLoopWithContinue', function() { - let insns = compileMainSnippet("let a = 5;" + - "while (a < 1) { a = 2; continue; }"); - let a = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - labelPre, - // condition - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new LessDyn(lhs), - new Jeqz(labelPost), - //body - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), - new Jmp(labelPre), // continue - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ] - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[11]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[2]); - }); - - it('whileLoopWithBreak', function() { - let insns = compileMainSnippet("let a = 5;" + - "while (a < 1) { a = 2; break; }"); - let a = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - labelPre, - // condition - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new LessDyn(lhs), - new Jeqz(labelPost), - //body - new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), - new Jmp(labelPost), //break - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ] - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[10]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[12]); - }); -}); - -describe("DoWhileLoopTest", function() { - it('doWhileLoopEmpty', function() { - let insns = compileMainSnippet("do {} while (true)"); - - let jumps = insns.filter(item => item instanceof Jmp); - - expect(jumps.length).to.equal(1); - - let jmpLabel = (jumps[0]).getTarget(); - - expect(jmpLabel).to.equal(insns[0]); - }); - - it('doWhileLoopWithBody', function() { - let insns = compileMainSnippet("let a = 5;" + - "do { a++ } while (a < 11);"); - - let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); - - expect(jumps.length).to.equal(2); - - let jgezLabel = (jumps[0]).getTarget(); - let jmpLabel = (jumps[1]).getTarget(); - - expect(jmpLabel).to.equal(insns[2]); - expect(jgezLabel).to.equal(insns[15]); - - expect(insns[13]).to.equal(jumps[0]); - expect(insns[14]).to.equal(jumps[1]); - }); - - it('doWhileLoopWithContinue', function() { - let insns = compileMainSnippet("let a = 5;" + - "do { a = 1; continue; } while (a < 1);"); - let a = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelCond = new Label(); - let labelPost = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - // body - labelPre, - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), - new Jmp(labelCond), // continue - // condition - labelCond, - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new LessDyn(lhs), - new Jeqz(labelPost), - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ] - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[5]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[6]); - }); - - it('doWhileLoopWithBreak', function() { - let insns = compileMainSnippet("let a = 5;" + - "do { a = 1; break; } while (a < 1);"); - let a = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let labelCond = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(a), - //body - labelPre, - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), - new Jmp(labelPost), // break - // condition - labelCond, - new LdaDyn(a), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new LessDyn(lhs), - new Jeqz(labelPost), - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ] - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check continue jumps to the expected instruction - let jmp = insns[5]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[13]); - }); -}); - -describe("LoopWithLabelTests", function() { - it('forLoopWithBreakWithLabel', function() { - let insns = compileMainSnippet(`loop1: - for (let i = 0; i < 5; ++i) { - for (let j = 0; j < 6; j++) { - break loop1; - } - }`); - let i = new VReg(); - let j = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let labelIncr = new Label(); - let labelPre1 = new Label(); - let labelPost1 = new Label(); - let labelIncr1 = new Label(); - let expected = [ - // initializer - new LdaiDyn(new Imm(ResultType.Int, 0.0)), - new StaDyn(i), - labelPre, - // condition - new LdaDyn(i), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 5.0)), - new LessDyn(lhs), - new Jeqz(labelPost), - - // second for - new LdaiDyn(new Imm(ResultType.Int, 0.0)), - new StaDyn(j), - labelPre1, - // condition - new LdaDyn(j), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 6.0)), - new LessDyn(lhs), - new Jeqz(labelPost1), - new Jmp(labelPost), - labelIncr1, - // incrementor - new LdaDyn(j), - new StaDyn(j), - new IncDyn(j), - new StaDyn(j), - new Tonumber(j), - // jump to the loop header - new Jmp(labelPre1), - labelPost1, - labelIncr, - // incrementor - new LdaDyn(i), - new StaDyn(i), - new IncDyn(i), - new StaDyn(i), - // jump to the loop header - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ]; - - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check break jumps to the expected instruction - let jmp = insns[16]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[31]); - }); - - it('forLoopWithContinueWithLabel', function() { - let insns = compileMainSnippet(`loop1: - loop2: - loop3: - for (let i = 0; i < 5; ++i) { - for (let j = 0; j < 6; j++) { - continue loop2; - } - }`); - let i = new VReg(); - let j = new VReg(); - let lhs = new VReg(); - let labelPre = new Label(); - let labelPost = new Label(); - let labelIncr = new Label(); - let labelPre1 = new Label(); - let labelPost1 = new Label(); - let labelIncr1 = new Label(); - let expected = [ - // initializer - new LdaiDyn(new Imm(ResultType.Int, 0.0)), - new StaDyn(i), - labelPre, - // condition - new LdaDyn(i), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 5.0)), - new LessDyn(lhs), - new Jeqz(labelPost), - - // second for - new LdaiDyn(new Imm(ResultType.Int, 0.0)), - new StaDyn(j), - labelPre1, - // condition - new LdaDyn(j), - new StaDyn(lhs), - new LdaiDyn(new Imm(ResultType.Int, 6.0)), - new LessDyn(lhs), - new Jeqz(labelPost1), - new Jmp(labelIncr), - labelIncr1, - // incrementor - new LdaDyn(j), - new StaDyn(j), - new IncDyn(j), - new StaDyn(j), - new Tonumber(j), - // jump to the loop header - new Jmp(labelPre1), - labelPost1, - labelIncr, - // incrementor - new LdaDyn(i), - new StaDyn(i), - new IncDyn(i), - new StaDyn(i), - // jump to the loop header - new Jmp(labelPre), - labelPost, - new ReturnUndefined() - ]; - - // check the instruction kinds are the same as we expect - expect(checkInstructions(insns, expected)).to.be.true; - // check break jumps to the expected instruction - let jmp = insns[16]; - let targetLabel = (jmp).getTarget(); - expect(targetLabel).to.equal(insns[25]); - }); -}); +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaIncdyn, + EcmaLessdyn, + EcmaReturnundefined, + EcmaTonumber, + Imm, + Jeqz, + Jmp, + Label, + LdaDyn, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("ForLoopTest", function () { + it('forLoopEmpty', function () { + let insns = compileMainSnippet("for (;;) {}"); + let labelPre = new Label(); + let labelPost = new Label(); + let labelIncr = new Label(); + let expected = [ + labelPre, + labelIncr, + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ]; + let jumps = insns.filter(item => item instanceof Jmp); + + expect(jumps.length).to.equal(1); + + let jmpLabel = (jumps[0]).getTarget(); + + expect(checkInstructions(insns, expected)).to.be.true; + expect(jmpLabel).to.equal(insns[0]); + }); + + it('forLoopWithInitializer', function () { + let insns = compileMainSnippet("for (let i = 0;;) {}"); + let jumps = insns.filter(item => item instanceof Jmp); + + expect(jumps.length).to.equal(1); + + let jmpLabel = (jumps[0]).getTarget(); + + expect(insns[4]).to.equal(jumps[0]); + expect(jmpLabel).to.equal(insns[2]); + }); + + it('forLoopWithInitializerAndCondition', function () { + let insns = compileMainSnippet("for (let i = 0; i < 5;) {}"); + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(2); + + let jgezLabel = (jumps[0]).getTarget(); + let jmpLabel = (jumps[1]).getTarget(); + + expect(jmpLabel).to.equal(insns[2]); + expect(jgezLabel).to.equal(insns[10]); + + expect(insns[7]).to.equal(jumps[0]); + expect(insns[9]).to.equal(jumps[1]); + }); + + it('forLoopWithInitializerAndConditionAndIncrementor', function () { + let insns = compileMainSnippet("for (let i = 0; i < 5; i++) {}"); + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(2); + + let jgezLabel = (jumps[0]).getTarget(); + let jmpLabel = (jumps[1]).getTarget(); + + expect(jmpLabel).to.equal(insns[2]); + expect(jgezLabel).to.equal(insns[15]); + + expect(insns[7]).to.equal(jumps[0]); + expect(insns[14]).to.equal(jumps[1]); + }); + + it('forLoopWithContinue', function () { + let insns = compileMainSnippet("for (let i = 0; i < 5; ++i) { continue; }"); + let i = new VReg(); + let lhs = new VReg(); + let operand = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let labelIncr = new Label(); + let expected = [ + // initializer + new LdaiDyn(new Imm(ResultType.Int, 0)), + new StaDyn(i), + labelPre, + // condition + new LdaDyn(i), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + // body + new Jmp(labelIncr), // continue + labelIncr, + // incrementor + new LdaDyn(i), + new StaDyn(operand), + new EcmaIncdyn(operand), + new StaDyn(i), + // jump to the loop header + new Jmp(new Label()), + labelPost, + new EcmaReturnundefined() + ]; + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[8]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[9]); + }); + + it('forLoopWithBreak', function () { + let insns = compileMainSnippet("for (let i = 0; i < 5; ++i) {break; }"); + let i = new VReg(); + let lhs = new VReg(); + let operand = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let labelIncr = new Label(); + let expected = [ + // initializer + new LdaiDyn(new Imm(ResultType.Int, 0)), + new StaDyn(i), + labelPre, + // condition + new LdaDyn(i), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + // body + new Jmp(labelPost), // break + // incrementor + labelIncr, + new LdaDyn(i), + new StaDyn(operand), + new EcmaIncdyn(operand), + new StaDyn(i), + // jump to the loop header + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ]; + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[8]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[15]); + }); +}); + +describe("LoopWithLabelTests", function () { + it('forLoopWithBreakWithLabel', function () { + let insns = compileMainSnippet(`loop1: + for (let i = 0; i < 5; ++i) { + for (let j = 0; j < 6; j++) { + break loop1; + } + }`); + let i = new VReg(); + let j = new VReg(); + let lhs = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let labelIncr = new Label(); + let labelPre1 = new Label(); + let labelPost1 = new Label(); + let labelIncr1 = new Label(); + let expected = [ + // initializer + new LdaiDyn(new Imm(ResultType.Int, 0.0)), + new StaDyn(i), + labelPre, + // condition + new LdaDyn(i), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 5.0)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + + // second for + new LdaiDyn(new Imm(ResultType.Int, 0.0)), + new StaDyn(j), + labelPre1, + // condition + new LdaDyn(j), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 6.0)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost1), + new Jmp(labelPost), + labelIncr1, + // incrementor + new LdaDyn(j), + new StaDyn(j), + new EcmaIncdyn(j), + new StaDyn(j), + new EcmaTonumber(j), + // jump to the loop header + new Jmp(labelPre1), + labelPost1, + labelIncr, + // incrementor + new LdaDyn(i), + new StaDyn(i), + new EcmaIncdyn(i), + new StaDyn(i), + // jump to the loop header + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ]; + + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check break jumps to the expected instruction + let jmp = insns[16]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[31]); + }); + + it('forLoopWithContinueWithLabel', function () { + let insns = compileMainSnippet(`loop1: + loop2: + loop3: + for (let i = 0; i < 5; ++i) { + for (let j = 0; j < 6; j++) { + continue loop2; + } + }`); + let i = new VReg(); + let j = new VReg(); + let lhs = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let labelIncr = new Label(); + let labelPre1 = new Label(); + let labelPost1 = new Label(); + let labelIncr1 = new Label(); + let expected = [ + // initializer + new LdaiDyn(new Imm(ResultType.Int, 0.0)), + new StaDyn(i), + labelPre, + // condition + new LdaDyn(i), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 5.0)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + + // second for + new LdaiDyn(new Imm(ResultType.Int, 0.0)), + new StaDyn(j), + labelPre1, + // condition + new LdaDyn(j), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 6.0)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost1), + new Jmp(labelIncr), + labelIncr1, + // incrementor + new LdaDyn(j), + new StaDyn(j), + new EcmaIncdyn(j), + new StaDyn(j), + new EcmaTonumber(j), + // jump to the loop header + new Jmp(labelPre1), + labelPost1, + labelIncr, + // incrementor + new LdaDyn(i), + new StaDyn(i), + new EcmaIncdyn(i), + new StaDyn(i), + // jump to the loop header + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ]; + + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check break jumps to the expected instruction + let jmp = insns[16]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[25]); + }); +}); diff --git a/ts2panda/tests/statements/forIn.test.ts b/ts2panda/tests/statements/forIn.test.ts index 93348bfc36..374f6c7b40 100755 --- a/ts2panda/tests/statements/forIn.test.ts +++ b/ts2panda/tests/statements/forIn.test.ts @@ -17,24 +17,26 @@ import { expect } from 'chai'; import 'mocha'; -import { couldStartTrivia } from 'typescript'; +import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; import { - CreateEmptyObject, - GetNextPropName, - GetPropertiesIterator, + EcmaCreateemptyobject, + EcmaGetnextpropname, + EcmaGetpropiterator, + EcmaReturnundefined, + EcmaStrictnoteqdyn, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, Jeqz, Jmp, Label, LdaDyn, - ReturnUndefined, StaDyn, - StrictNotEqDyn, VReg } from "../../src/irnodes"; import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("forInLoopTest", function() { - it("forInLoopwithEmptyObject", function() { +describe("forInLoopTest", function () { + it("forInLoopwithEmptyObject", function () { let insns = compileMainSnippet("for (let prop in {}) {}"); let prop = new VReg(); let temp = new VReg(); @@ -45,22 +47,22 @@ describe("forInLoopTest", function() { let loopStartLabel = new Label(); let loopEndLabel = new Label(); let expected = [ - new CreateEmptyObject(), + new EcmaCreateemptyobject(), new StaDyn(objInstance), - new GetPropertiesIterator(), + new EcmaGetpropiterator(), new StaDyn(iterReg), loopStartLabel, - new GetNextPropName(iterReg), + new EcmaGetnextpropname(iterReg), new StaDyn(rhs), - new StrictNotEqDyn(temp), + new EcmaStrictnoteqdyn(temp), new Jeqz(loopEndLabel), new LdaDyn(rhs), new StaDyn(prop), new Jmp(loopStartLabel), loopEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -69,7 +71,7 @@ describe("forInLoopTest", function() { expect(jumps.length).to.equal(2); }); - it("forInLoopWithExpressionAsLoopVariable", function() { + it("forInLoopWithExpressionAsLoopVariable", function () { let insns = compileMainSnippet(` let prop; let obj; @@ -77,31 +79,29 @@ describe("forInLoopTest", function() { } `); let temp = new VReg(); - let prop = new VReg(); - let obj = new VReg(); let iterReg = new VReg(); let rhs = new VReg(); let loopStartLabel = new Label(); let loopEndLabel = new Label(); let expected = [ - new LdaDyn(obj), - new GetPropertiesIterator(), + new EcmaTryldglobalbyname('obj'), + new EcmaGetpropiterator(), new StaDyn(iterReg), loopStartLabel, - new GetNextPropName(iterReg), + new EcmaGetnextpropname(iterReg), new StaDyn(rhs), - new StrictNotEqDyn(temp), + new EcmaStrictnoteqdyn(temp), new Jeqz(loopEndLabel), new LdaDyn(rhs), - new StaDyn(prop), + new EcmaTrystglobalbyname('prop'), new Jmp(loopStartLabel), loopEndLabel, ]; - insns = insns.slice(4, insns.length - 1); + insns = insns.slice(4, insns.length - 1); expect(checkInstructions(insns, expected)).to.be.true; let jmp = insns.find(item => (item instanceof Jmp)); @@ -110,7 +110,7 @@ describe("forInLoopTest", function() { expect(jeqz.getTarget()).to.equal(insns[insns.length - 1]); }); - it("forInLoopwithObjectwithContinue", function() { + it("forInLoopwithObjectwithContinue", function () { let insns = compileMainSnippet("for (let prop in {}) {continue; }"); let prop = new VReg(); let temp = new VReg(); @@ -121,15 +121,15 @@ describe("forInLoopTest", function() { let loopStartLabel = new Label(); let loopEndLabel = new Label(); let expected = [ - new CreateEmptyObject(), + new EcmaCreateemptyobject(), new StaDyn(objInstance), - new GetPropertiesIterator(), + new EcmaGetpropiterator(), new StaDyn(iterReg), loopStartLabel, - new GetNextPropName(iterReg), + new EcmaGetnextpropname(iterReg), new StaDyn(rhs), - new StrictNotEqDyn(temp), + new EcmaStrictnoteqdyn(temp), new Jeqz(loopEndLabel), new LdaDyn(rhs), new StaDyn(prop), @@ -137,7 +137,7 @@ describe("forInLoopTest", function() { new Jmp(loopStartLabel), loopEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -146,7 +146,7 @@ describe("forInLoopTest", function() { expect(jumps.length).to.equal(3); }); - it("forInLoopwithObjectwithBreak", function() { + it("forInLoopwithObjectwithBreak", function () { let insns = compileMainSnippet("for (let prop in {}) {break; }"); let prop = new VReg(); let temp = new VReg(); @@ -157,15 +157,15 @@ describe("forInLoopTest", function() { let loopStartLabel = new Label(); let loopEndLabel = new Label(); let expected = [ - new CreateEmptyObject(), + new EcmaCreateemptyobject(), new StaDyn(objInstance), - new GetPropertiesIterator(), + new EcmaGetpropiterator(), new StaDyn(iterReg), loopStartLabel, - new GetNextPropName(iterReg), + new EcmaGetnextpropname(iterReg), new StaDyn(rhs), - new StrictNotEqDyn(temp), + new EcmaStrictnoteqdyn(temp), new Jeqz(loopEndLabel), new LdaDyn(rhs), new StaDyn(prop), @@ -173,7 +173,7 @@ describe("forInLoopTest", function() { new Jmp(loopStartLabel), loopEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -181,4 +181,17 @@ describe("forInLoopTest", function() { expect(jumps.length).to.equal(3); }); + + it("ForIn SyntaxError", function () { + let source: string = `for ([(x, y)] in {}) { }`; + let errorThrown = false; + try { + compileMainSnippet(source); + } catch (err) { + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected); + errorThrown = true; + } + expect(errorThrown).to.be.true; + }); }); diff --git a/ts2panda/tests/statements/forOf.test.ts b/ts2panda/tests/statements/forOf.test.ts new file mode 100644 index 0000000000..bf2963edfe --- /dev/null +++ b/ts2panda/tests/statements/forOf.test.ts @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; +import { + EcmaCallithisrangedyn, + EcmaCreateemptyarray, + EcmaGetiterator, + EcmaIsfalse, + EcmaLdobjbyname, + EcmaReturnundefined, + EcmaStrictnoteqdyn, + EcmaThrowdyn, + EcmaThrowifnotobject, + Imm, + Jeqz, + Jmp, + Label, + LdaDyn, ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("ForOfLoopTest", function () { + it("forOfLoopWithEmptyArray", function () { + let insns = compileMainSnippet("for (let a of []) {}"); + let a = new VReg(); + let arrInstance = new VReg(); + let iterReg = new VReg(); + let nextMethodReg = new VReg(); + let resultObj = new VReg(); + let exceptionVreg = new VReg(); + let trueReg = new VReg(); + let done = new VReg(); + let value = new VReg(); + + let loopStartLabel = new Label(); + let loopEndLabel = new Label(); + let tryBeginLabel = new Label(); + let tryEndLabel = new Label(); + let catchBeginLabel = new Label(); + let isDone = new Label(); + + let expected = [ + new EcmaCreateemptyarray(), + new StaDyn(arrInstance), + new EcmaGetiterator(), + new StaDyn(iterReg), + new EcmaLdobjbyname("next", iterReg), + new StaDyn(nextMethodReg), + + new LdaDyn(new VReg()), + new StaDyn(done), + + tryBeginLabel, + new LdaDyn(trueReg), + new StaDyn(done), + loopStartLabel, + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + new StaDyn(resultObj), + new EcmaThrowifnotobject(resultObj), + new EcmaLdobjbyname("done", resultObj), + new EcmaIsfalse(), + new Jeqz(loopEndLabel), + new EcmaLdobjbyname("value", resultObj), + new StaDyn(value), + + new LdaDyn(new VReg()), + new StaDyn(done), + + new LdaDyn(value), + new StaDyn(a), + tryEndLabel, + + new Jmp(loopStartLabel), + + catchBeginLabel, + new StaDyn(exceptionVreg), + new LdaDyn(done), + new EcmaStrictnoteqdyn(trueReg), + new Jeqz(isDone), + new EcmaLdobjbyname("return", iterReg), + new StaDyn(nextMethodReg), + new EcmaStrictnoteqdyn(new VReg()), + new Jeqz(isDone), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + isDone, + new LdaDyn(exceptionVreg), + new EcmaThrowdyn(), + + loopEndLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(4); + }); + + it("forOfLoopWithContinue", function () { + let insns = compileMainSnippet("for (let a of []) {continue;}"); + let a = new VReg(); + let arrInstance = new VReg(); + let resultObj = new VReg(); + let trueReg = new VReg(); + let iterReg = new VReg(); + let exceptionVreg = new VReg(); + let nextMethodReg = new VReg(); + let done = new VReg(); + let value = new VReg(); + + let loopStartLabel = new Label(); + let loopEndLabel = new Label(); + let tryBeginLabel = new Label(); + let tryEndLabel = new Label(); + let catchBeginLabel = new Label(); + let isDone = new Label(); + let insertedtryBeginLabel = new Label(); + let insertedtryEndLabel = new Label(); + + let expected = [ + new EcmaCreateemptyarray(), + new StaDyn(arrInstance), + new EcmaGetiterator(), + new StaDyn(iterReg), + new EcmaLdobjbyname("next", iterReg), + new StaDyn(nextMethodReg), + + new LdaDyn(new VReg()), + new StaDyn(done), + + tryBeginLabel, + new LdaDyn(trueReg), + new StaDyn(done), + loopStartLabel, + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + new StaDyn(resultObj), + new EcmaThrowifnotobject(resultObj), + new EcmaLdobjbyname("done", resultObj), + new EcmaIsfalse(), + new Jeqz(loopEndLabel), + new EcmaLdobjbyname("value", resultObj), + new StaDyn(value), + + new LdaDyn(new VReg()), + new StaDyn(done), + + new LdaDyn(value), + new StaDyn(a), + + insertedtryBeginLabel, + insertedtryEndLabel, + new Jmp(loopStartLabel), + + tryEndLabel, + + new Jmp(loopStartLabel), + + catchBeginLabel, + new StaDyn(exceptionVreg), + new LdaDyn(done), + new EcmaStrictnoteqdyn(trueReg), + new Jeqz(isDone), + new EcmaLdobjbyname("return", iterReg), + new StaDyn(nextMethodReg), + new EcmaStrictnoteqdyn(new VReg()), + new Jeqz(isDone), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + isDone, + new LdaDyn(exceptionVreg), + new EcmaThrowdyn(), + + loopEndLabel, + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(5); + }); + + it("forOfLoopWithBreak", function () { + let insns = compileMainSnippet("for (let a of []) {break;}"); + let a = new VReg(); + let arrInstance = new VReg(); + let resultObj = new VReg(); + let exceptionVreg = new VReg(); + let iterReg = new VReg(); + let trueReg = new VReg(); + let nextMethodReg = new VReg(); + let done = new VReg(); + let value = new VReg(); + let loopStartLabel = new Label(); + let loopEndLabel = new Label(); + let tryBeginLabel = new Label(); + let tryEndLabel = new Label(); + let catchBeginLabel = new Label(); + let isDone = new Label(); + let noReturn = new Label(); + let insertedtryBeginLabel = new Label(); + let insertedtryEndLabel = new Label(); + + let expected = [ + new EcmaCreateemptyarray(), + new StaDyn(arrInstance), + new EcmaGetiterator(), + new StaDyn(iterReg), + new EcmaLdobjbyname("next", iterReg), + new StaDyn(nextMethodReg), + + new LdaDyn(new VReg()), + new StaDyn(done), + + tryBeginLabel, + new LdaDyn(trueReg), + new StaDyn(done), + loopStartLabel, + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + new StaDyn(resultObj), + new EcmaThrowifnotobject(resultObj), + new EcmaLdobjbyname("done", resultObj), + new EcmaIsfalse(), + new Jeqz(loopEndLabel), + new EcmaLdobjbyname("value", resultObj), + new StaDyn(value), + + new LdaDyn(new VReg()), + new StaDyn(done), + + new LdaDyn(value), + new StaDyn(a), + + insertedtryBeginLabel, + new EcmaLdobjbyname("return", iterReg), + new StaDyn(nextMethodReg), + new EcmaStrictnoteqdyn(new VReg()), // undefined + new Jeqz(noReturn), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + new StaDyn(new VReg()), + new EcmaThrowifnotobject(new VReg()), + noReturn, + insertedtryEndLabel, + new Jmp(loopEndLabel), + + tryEndLabel, + + new Jmp(loopStartLabel), + + catchBeginLabel, + new StaDyn(exceptionVreg), + new LdaDyn(done), + new EcmaStrictnoteqdyn(trueReg), + new Jeqz(isDone), + new EcmaLdobjbyname("return", iterReg), + new StaDyn(nextMethodReg), + new EcmaStrictnoteqdyn(new VReg()), + new Jeqz(isDone), + new EcmaCallithisrangedyn(new Imm(ResultType.Int, 1), [nextMethodReg, iterReg]), + isDone, + new LdaDyn(exceptionVreg), + new EcmaThrowdyn(), + + loopEndLabel, + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + + let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); + + expect(jumps.length).to.equal(6); + }); + + it("ForOf SyntaxError", function () { + let source: string = `for ([(x, y)] of []) {}`; + let errorThrown = false; + try { + compileMainSnippet(source); + } catch (err) { + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected); + errorThrown = true; + } + expect(errorThrown).to.be.true; + }); +}); diff --git a/ts2panda/tests/statements/functionDeclaration.test.ts b/ts2panda/tests/statements/functionDeclaration.test.ts new file mode 100644 index 0000000000..a62f826d80 --- /dev/null +++ b/ts2panda/tests/statements/functionDeclaration.test.ts @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaCopyrestargs, + EcmaDefinefuncdyn, + EcmaReturnundefined, + EcmaStglobalvar, + EcmaStlettoglobalrecord, + EcmaStricteqdyn, + Imm, + Jeqz, + Label, + LdaDyn, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { + GlobalVariable, + LocalVariable +} from "../../src/variable"; +import { checkInstructions, compileAllSnippet, SnippetCompiler } from "../utils/base"; + +describe("FunctionDeclarationTest", function () { + it('function definition in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("function foo() {}"); + let funcName = "foo"; + let expected = [ + new EcmaDefinefuncdyn(funcName, new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar(funcName), + new EcmaReturnundefined() + ]; + let insns = snippetCompiler.getGlobalInsns(); + let globalScope = snippetCompiler.getGlobalScope(); + expect(checkInstructions(insns, expected)).to.be.true; + let foo = globalScope!.findLocal(funcName); + expect(foo != undefined).to.be.true; + expect(foo instanceof GlobalVariable).to.be.true; + }); + + it('function redefinition in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(` + function foo() {} + function foo() {} + `); + let expected = [ + new EcmaDefinefuncdyn("#2#foo", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStglobalvar("foo"), + new EcmaReturnundefined() + ]; + let insns = snippetCompiler.getGlobalInsns(); + let globalScope = snippetCompiler.getGlobalScope(); + expect(checkInstructions(insns, expected)).to.be.true; + let foo = globalScope!.findLocal("foo"); + expect(foo != undefined).to.be.true; + expect(foo instanceof GlobalVariable).to.be.true; + }); + + it('function definition inside a function', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`function out() {function foo() {}}`); + let funcReg = new VReg(); + let expected = [ + new EcmaDefinefuncdyn("foo", new Imm(ResultType.Int, 0), new VReg()), + new StaDyn(funcReg), + + new EcmaReturnundefined() + ]; + let functionPg = snippetCompiler.getPandaGenByName("out"); + let insns = functionPg!.getInsns(); + let functionScope = functionPg!.getScope(); + + expect(checkInstructions(insns!, expected)).to.be.true; + let foo = functionScope!.findLocal("foo"); + expect(foo != undefined).to.be.true; + expect(foo instanceof LocalVariable).to.be.true; + let parameterLength = functionPg!.getParameterLength(); + expect(parameterLength == 0).to.be.true; + }); + + it("function expression", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("let foo = function() {}"); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new EcmaDefinefuncdyn("foo", new Imm(ResultType.Int, 0), new VReg()), + new EcmaStlettoglobalrecord("foo"), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("Parameters with initializer", function () { + let compilerunit = compileAllSnippet("function test(a, b = 1) {}"); + let undefinedVReg = new VReg(); + let value = new VReg(); + let endLabel = new Label(); + + let expected_main = [ + new EcmaDefinefuncdyn("test", new Imm(ResultType.Int, 1), new VReg()), + new EcmaStglobalvar("test"), + new EcmaReturnundefined() + ]; + let expected_func = [ + // func_test_0 + new LdaDyn(new VReg()), + new EcmaStricteqdyn(undefinedVReg), + new Jeqz(endLabel), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new StaDyn(value), + endLabel, + new EcmaReturnundefined(), + ]; + + compilerunit.forEach(element => { + if (element.internalName == "func_main_0") { + let insns = element.getInsns(); + expect(checkInstructions(insns, expected_main)).to.be.true; + } else if (element.internalName == "test") { + let insns = element.getInsns(); + expect(checkInstructions(insns, expected_func)).to.be.true; + let parameterLength = element.getParameterLength(); + expect(parameterLength == 1).to.be.true; + } + }); + }); + + it("Rest Parameters", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`function test(a, ...b) {}`); + + let idx = new Imm(ResultType.Int, 1); + let lastParam = new VReg(); + let expected_func = [ + // func_test_0 + new EcmaCopyrestargs(idx), + new StaDyn(lastParam), + new EcmaReturnundefined(), + ]; + + let functionPg = snippetCompiler.getPandaGenByName("test"); + let insns = functionPg!.getInsns(); + + expect(checkInstructions(insns, expected_func)).to.be.true; + }); +}); diff --git a/ts2panda/tests/returnStatement.test.ts b/ts2panda/tests/statements/return.test.ts similarity index 68% rename from ts2panda/tests/returnStatement.test.ts rename to ts2panda/tests/statements/return.test.ts index 9c4b77a7a3..7528c8dffc 100644 --- a/ts2panda/tests/returnStatement.test.ts +++ b/ts2panda/tests/statements/return.test.ts @@ -17,12 +17,12 @@ import { expect } from 'chai'; import 'mocha'; -import { ReturnUndefined } from "../src/irnodes"; -import { compileMainSnippet } from "./utils/base"; +import { EcmaReturnundefined } from "../../src/irnodes"; +import { compileMainSnippet } from "../utils/base"; -describe("ReturnStatementTest", function() { - it('exitGlobalScope', function() { - let insns = compileMainSnippet("var a;"); - expect(insns[insns.length - 1] instanceof ReturnUndefined).to.be.true; - }); +describe("ReturnStatementTest", function () { + it('exitGlobalScope', function () { + let insns = compileMainSnippet("var a;"); + expect(insns[insns.length - 1] instanceof EcmaReturnundefined).to.be.true; + }); }); diff --git a/ts2panda/tests/statements/switch.test.ts b/ts2panda/tests/statements/switch.test.ts index 2a04ef11be..91cb0a1255 100755 --- a/ts2panda/tests/statements/switch.test.ts +++ b/ts2panda/tests/statements/switch.test.ts @@ -18,24 +18,23 @@ import { } from 'chai'; import 'mocha'; import { + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaStrictnoteqdyn, + EcmaTryldglobalbyname, Imm, Jeqz, Jmp, Jnez, - Label, - LdaDyn, - LdaiDyn, + Label, LdaiDyn, ResultType, - ReturnDyn, - ReturnUndefined, StaDyn, - StrictNotEqDyn, VReg } from "../../src/irnodes"; import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("switchTest", function() { - it("single case", function() { +describe("switchTest", function () { + it("single case", function () { let insns = compileMainSnippet("let a = 0; switch (a) {case 0 : ;}"); let a = new VReg(); let rhs = new VReg(); @@ -43,32 +42,31 @@ describe("switchTest", function() { let switchEndLabel = new Label(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), // switch body - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(rhs), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel), new Jmp(switchEndLabel), // switch cases caseLabel, switchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; expect((insns[6]).getTarget() === insns[8]).to.be.true; expect((insns[7]).getTarget() === insns[9]).to.be.true; }); - it("multiple cases without break", function() { + it("multiple cases without break", function () { let insns = compileMainSnippet(`let a = 0; switch (a) { case 0 : ; case 1 : ; default : ; }`); - let a = new VReg(); let rhs = new VReg(); let caseLabel_0 = new Label(); let caseLabel_1 = new Label(); @@ -76,15 +74,15 @@ describe("switchTest", function() { let switchEndLabel = new Label(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), // switch body - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(rhs), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_0), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_1), new Jmp(defaultLabel), // cases @@ -93,19 +91,18 @@ describe("switchTest", function() { // default case defaultLabel, switchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("multiple cases with default", function() { + it("multiple cases with default", function () { let insns = compileMainSnippet(`let a = 0; switch (a) { case 0 : break; case 1 : break; default : ; }`); - let a = new VReg(); let rhs = new VReg(); let caseLabel_0 = new Label(); let caseLabel_1 = new Label(); @@ -113,15 +110,15 @@ describe("switchTest", function() { let switchEndLabel = new Label(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), // switch body - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(rhs), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_0), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_1), new Jmp(defaultLabel), // switch cases @@ -131,33 +128,32 @@ describe("switchTest", function() { new Jmp(switchEndLabel), defaultLabel, switchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("multiple cases without default", function() { + it("multiple cases without default", function () { let insns = compileMainSnippet(`let a = 0; switch (a) { case 0 : break; case 1 : break; }`); - let a = new VReg(); let rhs = new VReg(); let caseLabel_0 = new Label(); let caseLabel_1 = new Label(); let switchEndLabel = new Label(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), // switch body - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(rhs), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_0), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_1), new Jmp(switchEndLabel), // switch cases @@ -166,19 +162,18 @@ describe("switchTest", function() { caseLabel_1, new Jmp(switchEndLabel), switchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it("multiple cases with default surrounded by cases", function() { + it("multiple cases with default surrounded by cases", function () { let insns = compileMainSnippet(`let a = 0; switch (a) { case 0 : break; default : ; case 1 : ; }`); - let a = new VReg(); let rhs = new VReg(); let caseLabel_0 = new Label(); let caseLabel_1 = new Label(); @@ -186,15 +181,15 @@ describe("switchTest", function() { let switchEndLabel = new Label(); let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), // switch body - new LdaDyn(a), + new EcmaTryldglobalbyname('a'), new StaDyn(rhs), new LdaiDyn(new Imm(ResultType.Int, 0)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_0), new LdaiDyn(new Imm(ResultType.Int, 1)), - new StrictNotEqDyn(rhs), + new EcmaStrictnoteqdyn(rhs), new Jeqz(caseLabel_1), new Jmp(defaultLabel), // switch cases @@ -204,7 +199,7 @@ describe("switchTest", function() { defaultLabel, caseLabel_1, switchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); diff --git a/ts2panda/tests/tryCatch.test.ts b/ts2panda/tests/statements/tryCatch.test.ts similarity index 78% rename from ts2panda/tests/tryCatch.test.ts rename to ts2panda/tests/statements/tryCatch.test.ts index b280676bba..7114b171ca 100644 --- a/ts2panda/tests/tryCatch.test.ts +++ b/ts2panda/tests/statements/tryCatch.test.ts @@ -18,27 +18,27 @@ import { } from 'chai'; import 'mocha'; import { + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaThrowdyn, + EcmaTrystglobalbyname, Imm, Jmp, Label, LdaDyn, LdaiDyn, ResultType, - ReturnDyn, - ReturnUndefined, StaDyn, - ThrowDyn, VReg -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "./utils/base"; +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; -describe("TryCatch", function() { - it('tryCatch', function() { +describe("TryCatch", function () { + it('tryCatch', function () { let insns = compileMainSnippet(`let a = 0; try {a = 1;} catch {a = 2;}`); - let a = new VReg(); let tryBeginLabel = new Label(); let tryEndLabel = new Label(); let catchBeginLabel = new Label(); @@ -46,28 +46,27 @@ describe("TryCatch", function() { let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), tryBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), tryEndLabel, new Jmp(catchEndLabel), catchBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), catchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it('tryCatchWithIdentifier', function() { + it('tryCatchWithIdentifier', function () { let insns = compileMainSnippet(`let a = 0; try {a = 1;} catch(err) {a = 2;}`); - let a = new VReg(); let tryBeginLabel = new Label(); let tryEndLabel = new Label(); let catchBeginLabel = new Label(); @@ -76,29 +75,28 @@ describe("TryCatch", function() { let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), tryBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), tryEndLabel, new Jmp(catchEndLabel), catchBeginLabel, new StaDyn(err), new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), catchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it('tryFinally', function() { + it('tryFinally', function () { let insns = compileMainSnippet(`let a = 0; try {a = 1;} finally {a = 3;}`); - let a = new VReg(); let tryBeginLabel = new Label(); let tryEndLabel = new Label(); let catchBeginLabel = new Label(); @@ -107,34 +105,33 @@ describe("TryCatch", function() { let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), tryBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), tryEndLabel, new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), new Jmp(catchEndLabel), catchBeginLabel, new StaDyn(exceptionVreg), new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), new LdaDyn(exceptionVreg), - new ThrowDyn(), + new EcmaThrowdyn(), catchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; }); - it('tryCatchFinally', function() { + it('tryCatchFinally', function () { let insns = compileMainSnippet(`let a = 0; try {a = 1;} catch {a = 2;} finally {a = 3;}`); - let a = new VReg(); let exceptionVreg = new VReg(); let tryBeginLabel = new Label(); let tryEndLabel = new Label(); @@ -147,29 +144,29 @@ describe("TryCatch", function() { let expected = [ new LdaiDyn(new Imm(ResultType.Int, 0)), - new StaDyn(a), + new EcmaStlettoglobalrecord('a'), tryBeginLabel, nestedTryBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), nestedTryEndLabel, new Jmp(tryEndLabel), nestedCatchBeginLabel, new LdaiDyn(new Imm(ResultType.Int, 2)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), nestedCatchEndLabel, tryEndLabel, new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), new Jmp(catchEndLabel), catchBeginLabel, new StaDyn(exceptionVreg), new LdaiDyn(new Imm(ResultType.Int, 3)), - new StaDyn(a), + new EcmaTrystglobalbyname('a'), new LdaDyn(exceptionVreg), - new ThrowDyn(), + new EcmaThrowdyn(), catchEndLabel, - new ReturnUndefined() + new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; diff --git a/ts2panda/tests/declaration.test.ts b/ts2panda/tests/statements/variableDeclaration.test.ts similarity index 51% rename from ts2panda/tests/declaration.test.ts rename to ts2panda/tests/statements/variableDeclaration.test.ts index 49f6182632..51f1082baf 100644 --- a/ts2panda/tests/declaration.test.ts +++ b/ts2panda/tests/statements/variableDeclaration.test.ts @@ -1,378 +1,248 @@ -/* - * Copyright (c) 2021 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 { - expect -} from 'chai'; -import 'mocha'; -import { - CopyRestArgs, - DefinefuncDyn, - Imm, - Jeqz, - Label, - LdaDyn, - LdaiDyn, - ResultType, - ReturnUndefined, - StaDyn, - StGlobalVar, - StrictEqDyn, - VReg -} from "../src/irnodes"; -import { - FunctionScope, - GlobalScope -} from "../src/scope"; -import { - GlobalVariable, - LocalVariable -} from "../src/variable"; -import { checkInstructions, compileAllSnippet, SnippetCompiler } from "./utils/base"; -import { DiagnosticCode } from '../src/diagnostic'; - -describe("DeclarationTest", function() { - - it('var i in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - - snippetCompiler.compile("var i;"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - - let expected = [ - new LdaDyn(new VReg()), - new StGlobalVar("i"), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let v = globalScope.findLocal("i"); - expect(v instanceof GlobalVariable).to.be.true; - }); - - it('let i in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("let i;"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let v = globalScope.findLocal("i"); - expect(v instanceof LocalVariable).to.be.true; - }); - - it('const i in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("const i = 5;"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let v = globalScope.findLocal("i"); - expect(v instanceof LocalVariable).to.be.true; - }); - - it('var i = 5 in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("var i = 5;"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - let expected = [ - new LdaDyn(new VReg()), - new StGlobalVar("i"), - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StGlobalVar("i"), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let v = globalScope.findLocal("i"); - expect(v instanceof GlobalVariable).to.be.true; - }); - - it('let i = 5 in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("let i = 5;"); - let globalScope = snippetCompiler.getGlobalScope(); - let insns = snippetCompiler.getGlobalInsns(); - let i = new VReg(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let v = globalScope.findLocal("i"); - expect(v instanceof LocalVariable).to.be.true; - }); - - it('var i, j in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("var i, j;"); - let globalScope = snippetCompiler.getGlobalScope(); - let i = globalScope.findLocal("i"); - expect(i instanceof GlobalVariable).to.be.true; - let j = globalScope.findLocal("j"); - expect(j instanceof GlobalVariable).to.be.true; - }); - - it('let i, j in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("let i, j;"); - let globalScope = snippetCompiler.getGlobalScope(); - let i = globalScope.findLocal("i"); - expect(i instanceof LocalVariable).to.be.true; - let j = globalScope.findLocal("j"); - expect(j instanceof LocalVariable).to.be.true; - }); - - it('const i, j in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("const i=5, j=5;"); - let globalScope = snippetCompiler.getGlobalScope(); - let i = globalScope.findLocal("i"); - expect(i instanceof LocalVariable).to.be.true; - let j = globalScope.findLocal("j"); - expect(j instanceof LocalVariable).to.be.true; - }); - - it('var i in a function scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("function a() {var i;}"); - let funcPg = snippetCompiler.getPandaGenByName("func_a_1"); - let functionScope = funcPg!.getScope(); - let insns = funcPg!.getInsns(); - let builtInUndefinedReg = new VReg(); - let v = new VReg(); - let expected = [ - new LdaDyn(builtInUndefinedReg), - new StaDyn(v), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let i = functionScope.findLocal("i"); - expect(i).to.not.be.equal(undefined); - expect(i instanceof LocalVariable).to.be.true; - }); - - it('let i in a function scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("function a() {let i;}"); - let funcPg = snippetCompiler.getPandaGenByName("func_a_1"); - let functionScope = funcPg!.getScope(); - let insns = funcPg!.getInsns(); - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let i = functionScope.findLocal("i"); - expect(i).to.be.equal(undefined); - }); - - it('const i in a function scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("function a() {const i = 5;}"); - let funcPg = snippetCompiler.getPandaGenByName("func_a_1"); - let functionScope = funcPg!.getScope(); - let insns = funcPg!.getInsns(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let i = functionScope.findLocal("i"); - expect(i).to.be.equal(undefined); - }); - - it('let i in a local scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("{let i;}"); - let funcPg = snippetCompiler.getPandaGenByName("func_main_0"); - let localScope = funcPg!.getScope(); - let insns = funcPg!.getInsns(); - - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let i = localScope!.findLocal("i"); - expect(i).to.be.equal(undefined); - }); - - it('let declaration syntax error', function() { - let errorThrown = false; - let snippetCompiler = new SnippetCompiler(); - try { - snippetCompiler.compile("label: let i = 5;"); - } catch (err) { - expect(err.code).to.equal(DiagnosticCode.Lexical_declaration_let_not_allowed_in_statement_position); - errorThrown = true; - } - expect(errorThrown).to.be.true; - }); - - it('const i in a local scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("{const i = 5;}"); - let insns = snippetCompiler.getGlobalInsns(); - let scope = snippetCompiler.getGlobalScope(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - let i = scope!.findLocal("i"); - expect(i == undefined).to.be.true; // not in global - }); - - it('function definition in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("function foo() {}"); - let funcName = "foo"; - let internalName = "func_foo_1"; - let expected = [ - new DefinefuncDyn(internalName, new VReg()), - new StGlobalVar(funcName), - new ReturnUndefined() - ]; - let insns = snippetCompiler.getGlobalInsns(); - let globalScope = snippetCompiler.getGlobalScope(); - expect(checkInstructions(insns, expected)).to.be.true; - let foo = globalScope!.findLocal("foo"); - expect(foo != undefined).to.be.true; - expect(foo instanceof GlobalVariable).to.be.true; - }); - - it('function redefinition in the global scope', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(` - function foo() {} - function foo() {} - `); - let expected = [ - new DefinefuncDyn("func_foo_2", new VReg()), - new StGlobalVar("foo"), - new ReturnUndefined() - ]; - let insns = snippetCompiler.getGlobalInsns(); - let globalScope = snippetCompiler.getGlobalScope(); - expect(checkInstructions(insns, expected)).to.be.true; - let foo = globalScope!.findLocal("foo"); - expect(foo != undefined).to.be.true; - expect(foo instanceof GlobalVariable).to.be.true; - }); - - it('function definition inside a function', function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(`function out() {function foo() {}}`); - let funcReg = new VReg(); - let expected = [ - new DefinefuncDyn("func_foo_2", new VReg()), - new StaDyn(funcReg), - - new ReturnUndefined() - ]; - let functionPg = snippetCompiler.getPandaGenByName("func_out_1"); - let insns = functionPg!.getInsns(); - let functionScope = functionPg!.getScope(); - - expect(checkInstructions(insns!, expected)).to.be.true; - let foo = functionScope!.findLocal("foo"); - expect(foo != undefined).to.be.true; - expect(foo instanceof LocalVariable).to.be.true; - let parameterLength = functionPg!.getParameterLength(); - expect(parameterLength == 0).to.be.true; - }); - - it("function expression", function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile("let foo = function() {}"); - let insns = snippetCompiler.getGlobalInsns(); - let func = new VReg(); - let expected = [ - new DefinefuncDyn("func_foo_1", new VReg()), - new StaDyn(func), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("Parameters with initializer", function() { - let compilerunit = compileAllSnippet("function test(a, b = 1) {}"); - let undefinedVReg = new VReg(); - let value = new VReg(); - let endLabel = new Label(); - - let expected_main = [ - new DefinefuncDyn("func_test_1", new VReg()), - new StGlobalVar("test"), - new ReturnUndefined() - ]; - let expected_func = [ - // func_test_0 - new LdaDyn(new VReg()), - new StrictEqDyn(undefinedVReg), - new Jeqz(endLabel), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(value), - endLabel, - new ReturnUndefined(), - ]; - - compilerunit.forEach(element => { - if (element.internalName == "func_main_0") { - let insns = element.getInsns(); - expect(checkInstructions(insns, expected_main)).to.be.true; - } else if (element.internalName == "func_test_1") { - let insns = element.getInsns(); - expect(checkInstructions(insns, expected_func)).to.be.true; - let parameterLength = element.getParameterLength(); - expect(parameterLength == 1).to.be.true; - } - }); - }); - - it("Rest Parameters", function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(`function test(a, ...b) {}`); - - let idx = new Imm(ResultType.Int, 1); - let lastParam = new VReg(); - let expected_func = [ - // func_test_0 - new CopyRestArgs(idx), - new StaDyn(lastParam), - new ReturnUndefined(), - ]; - - let functionPg = snippetCompiler.getPandaGenByName("func_test_1"); - let insns = functionPg!.getInsns(); - - expect(checkInstructions(insns, expected_func)).to.be.true; - }); -}); +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; +import { + EcmaReturnundefined, + EcmaStconsttoglobalrecord, + EcmaStglobalvar, + EcmaStlettoglobalrecord, + Imm, + LdaDyn, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { + FunctionScope, + GlobalScope +} from "../../src/scope"; +import { + GlobalVariable, + LocalVariable +} from "../../src/variable"; +import { checkInstructions, SnippetCompiler } from "../utils/base"; + +describe("VariableDeclarationTest", function () { + + it('var i in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + + snippetCompiler.compile("var i;"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + + let expected = [ + new LdaDyn(new VReg()), + new EcmaStglobalvar("i"), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let v = globalScope.findLocal("i"); + expect(v instanceof GlobalVariable).to.be.true; + }); + + it('let i in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("let i;"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new LdaDyn(new VReg()), + new EcmaStlettoglobalrecord('i'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let v = globalScope.findLocal("i"); + expect(v instanceof LocalVariable).to.be.true; + }); + + it('const i in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("const i = 5;"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStconsttoglobalrecord('i'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let v = globalScope.findLocal("i"); + expect(v instanceof LocalVariable).to.be.true; + }); + + it('var i = 5 in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("var i = 5;"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new LdaDyn(new VReg()), + new EcmaStglobalvar("i"), + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStglobalvar("i"), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let v = globalScope.findLocal("i"); + expect(v instanceof GlobalVariable).to.be.true; + }); + + it('let i = 5 in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("let i = 5;"); + let globalScope = snippetCompiler.getGlobalScope(); + let insns = snippetCompiler.getGlobalInsns(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('i'), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let v = globalScope.findLocal("i"); + expect(v instanceof LocalVariable).to.be.true; + }); + + it('var i, j in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("var i, j;"); + let globalScope = snippetCompiler.getGlobalScope(); + let i = globalScope.findLocal("i"); + expect(i instanceof GlobalVariable).to.be.true; + let j = globalScope.findLocal("j"); + expect(j instanceof GlobalVariable).to.be.true; + }); + + it('let i, j in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("let i, j;"); + let globalScope = snippetCompiler.getGlobalScope(); + let i = globalScope.findLocal("i"); + expect(i instanceof LocalVariable).to.be.true; + let j = globalScope.findLocal("j"); + expect(j instanceof LocalVariable).to.be.true; + }); + + it('const i, j in the global scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("const i=5, j=5;"); + let globalScope = snippetCompiler.getGlobalScope(); + let i = globalScope.findLocal("i"); + expect(i instanceof LocalVariable).to.be.true; + let j = globalScope.findLocal("j"); + expect(j instanceof LocalVariable).to.be.true; + }); + + it('var i in a function scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("function a() {var i;}"); + let funcPg = snippetCompiler.getPandaGenByName("a"); + let functionScope = funcPg!.getScope(); + let insns = funcPg!.getInsns(); + let expected = [ + new LdaDyn(new VReg()), + new StaDyn(new VReg()), + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + let i = functionScope.findLocal("i"); + expect(i).to.not.be.equal(undefined); + expect(i instanceof LocalVariable).to.be.true; + }); + + it('let i in a function scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("function a() {let i;}"); + let funcPg = snippetCompiler.getPandaGenByName("a"); + let functionScope = funcPg!.getScope(); + let insns = funcPg!.getInsns(); + let expected = [ + new LdaDyn(new VReg()), + new StaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let i = functionScope.findLocal("i"); + expect(i).to.be.equal(undefined); + }); + + it('const i in a function scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("function a() {const i = 5;}"); + let funcPg = snippetCompiler.getPandaGenByName("a"); + let functionScope = funcPg!.getScope(); + let insns = funcPg!.getInsns(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new StaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let i = functionScope.findLocal("i"); + expect(i).to.be.equal(undefined); + }); + + it('let i in a local scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("{let i;}"); + let funcPg = snippetCompiler.getPandaGenByName("func_main_0"); + let localScope = funcPg!.getScope(); + let insns = funcPg!.getInsns(); + + let expected = [ + new LdaDyn(new VReg()), + new StaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let i = localScope!.findLocal("i"); + expect(i).to.be.equal(undefined); + }); + + it('let declaration syntax error', function () { + let errorThrown = false; + let snippetCompiler = new SnippetCompiler(); + try { + snippetCompiler.compile("label: let i = 5;"); + } catch (err) { + expect(err instanceof DiagnosticError).to.be.true; + expect((err).code).to.equal(DiagnosticCode.Lexical_declaration_let_not_allowed_in_statement_position); + errorThrown = true; + } + expect(errorThrown).to.be.true; + }); + + it('const i in a local scope', function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile("{const i = 5;}"); + let insns = snippetCompiler.getGlobalInsns(); + let scope = snippetCompiler.getGlobalScope(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new StaDyn(new VReg()), + new EcmaReturnundefined() + ]; + expect(checkInstructions(insns, expected)).to.be.true; + let i = scope!.findLocal("i"); + expect(i == undefined).to.be.true; // not in global + }); +}); diff --git a/ts2panda/tests/statements/while.test.ts b/ts2panda/tests/statements/while.test.ts new file mode 100644 index 0000000000..6e40c78dc9 --- /dev/null +++ b/ts2panda/tests/statements/while.test.ts @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 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 { + expect +} from 'chai'; +import 'mocha'; +import { + EcmaAdd2dyn, + EcmaIstrue, + EcmaLessdyn, + EcmaReturnundefined, + EcmaStlettoglobalrecord, + EcmaTryldglobalbyname, + EcmaTrystglobalbyname, + Imm, + Jeqz, + Jgez, + Jmp, + Label, + LdaDyn, + LdaiDyn, + ResultType, + StaDyn, + VReg +} from "../../src/irnodes"; +import { checkInstructions, compileMainSnippet } from "../utils/base"; + +describe("WhileLoopTest", function () { + it("while (true) {}", function () { + let insns = compileMainSnippet("while (true) {}"); + let labelPre = new Label(); + let labelPost = new Label(); + let expected = [ + labelPre, + new LdaDyn(new VReg()), + new EcmaIstrue(), + new Jeqz(labelPost), + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ]; + + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it("while (a + b) {}", function () { + let insns = compileMainSnippet("let a, b; while (a + b) {}"); + let loopBegin = new Label(); + let loopEnd = new Label(); + let lhs = new VReg(); + let expected = [ + loopBegin, + // a + b + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new EcmaTryldglobalbyname('b'), + new EcmaAdd2dyn(lhs), + new EcmaIstrue(), + new Jeqz(loopEnd), + // body + new Jmp(loopBegin), + loopEnd + ]; + + insns = insns.slice(4, insns.length - 1); // skip let a, b and return.dyn + expect(checkInstructions(insns, expected)).to.be.true; + }); + + it('whileLoopWithBody', function () { + let insns = compileMainSnippet(` + let a; + while (a < 0) { a = 1; } + `); + + let lhs = new VReg(); + let loopBegin = new Label(); + let loopEnd = new Label(); + let expected = [ + loopBegin, + // condition + // compute lhs + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + // compute rhs + new LdaiDyn(new Imm(ResultType.Int, 0)), + new EcmaLessdyn(lhs), + new Jeqz(loopEnd), + + // body + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaTrystglobalbyname('a'), + new Jmp(loopBegin), + + loopEnd, + ]; + + insns = insns.slice(2, insns.length - 1); // skip let a and return.dyn + expect(checkInstructions(insns, expected)).to.be.true; + expect((insns[5]).getTarget() === insns[insns.length - 1]).to.be.true; + expect((insns[insns.length - 2]).getTarget() === insns[0]).to.be.true; + }); + + it('whileLoopWithContinue', function () { + let insns = compileMainSnippet("let a = 5;" + + "while (a < 1) { a = 2; continue; }"); + let lhs = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + labelPre, + // condition + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + //body + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaTrystglobalbyname('a'), + new Jmp(labelPre), // continue + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ] + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[11]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[2]); + }); + + it('whileLoopWithBreak', function () { + let insns = compileMainSnippet("let a = 5;" + + "while (a < 1) { a = 2; break; }"); + let lhs = new VReg(); + let labelPre = new Label(); + let labelPost = new Label(); + let expected = [ + new LdaiDyn(new Imm(ResultType.Int, 5)), + new EcmaStlettoglobalrecord('a'), + labelPre, + // condition + new EcmaTryldglobalbyname('a'), + new StaDyn(lhs), + new LdaiDyn(new Imm(ResultType.Int, 1)), + new EcmaLessdyn(lhs), + new Jeqz(labelPost), + //body + new LdaiDyn(new Imm(ResultType.Int, 2)), + new EcmaTrystglobalbyname('a'), + new Jmp(labelPost), //break + new Jmp(labelPre), + labelPost, + new EcmaReturnundefined() + ] + // check the instruction kinds are the same as we expect + expect(checkInstructions(insns, expected)).to.be.true; + // check continue jumps to the expected instruction + let jmp = insns[10]; + let targetLabel = (jmp).getTarget(); + expect(targetLabel).to.equal(insns[12]); + }); +}); diff --git a/ts2panda/tests/strictmode/strictmode.test.ts b/ts2panda/tests/strictmode/strictmode.test.ts index 224cb0b600..19c0922233 100755 --- a/ts2panda/tests/strictmode/strictmode.test.ts +++ b/ts2panda/tests/strictmode/strictmode.test.ts @@ -14,12 +14,12 @@ */ import { expect } from 'chai'; -import * as ts from "typescript"; import { readFileSync } from "fs"; +import * as ts from "typescript"; import { isStrictMode, setGlobalStrict } from '../../src/strictMode'; -import jshelpers = require('../../src/jshelpers'); -import { getCompileOptions } from '../utils/base'; import { isFunctionLikeDeclaration } from '../../src/syntaxCheckHelper'; +import { getCompileOptions } from '../utils/base'; +import jshelpers = require('../../src/jshelpers'); function createSourceFile(filename: string): ts.SourceFile { let sourceFile = ts.createSourceFile( @@ -41,15 +41,15 @@ function recordNodes(node: ts.Node, flag: boolean): boolean { return false; } -describe("strict_mode", function() { - it('global strict mode', function() { +describe("strict_mode", function () { + it('global strict mode', function () { let node = createSourceFile("tests/strictmode/global.js"); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, getCompileOptions())); expect(isStrictMode(node)).to.be.true; recordNodes(node, true); }); - it('function strict mode', function() { + it('function strict mode', function () { let node = createSourceFile("tests/strictmode/function.js"); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, getCompileOptions())); expect(isStrictMode(node)).to.be.false; @@ -68,7 +68,7 @@ describe("strict_mode", function() { }); }); - it('function nest1 strict mode', function() { + it('function nest1 strict mode', function () { let node = createSourceFile("tests/strictmode/function_nest1.js"); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, getCompileOptions())); expect(isStrictMode(node)).to.be.false; @@ -81,7 +81,7 @@ describe("strict_mode", function() { }); }); - it('function nest2 strict mode', function() { + it('function nest2 strict mode', function () { let node = createSourceFile("tests/strictmode/function_nest2.js"); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, getCompileOptions())); expect(isStrictMode(node)).to.be.false; diff --git a/ts2panda/tests/tsconfig.mac.json b/ts2panda/tests/tsconfig.mac.json new file mode 100644 index 0000000000..23c1b38179 --- /dev/null +++ b/ts2panda/tests/tsconfig.mac.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../build-mac", + "incremental": true, + "tsBuildInfoFile": "../build-mac/tests/tsconfig.tsbuildinfo", + }, + "references": [ + { "path": "../src" } + ] + } + \ No newline at end of file diff --git a/ts2panda/tests/tsconfig.win.json b/ts2panda/tests/tsconfig.win.json new file mode 100644 index 0000000000..edaef63e1b --- /dev/null +++ b/ts2panda/tests/tsconfig.win.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../build-win", + "incremental": true, + "tsBuildInfoFile": "../build-win/tests/tsconfig.tsbuildinfo", + }, + "references": [ + { "path": "../src" } + ] + } + \ No newline at end of file diff --git a/ts2panda/tests/unary.test.ts b/ts2panda/tests/unary.test.ts deleted file mode 100644 index 3be3b735be..0000000000 --- a/ts2panda/tests/unary.test.ts +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 2021 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 { - expect -} from 'chai'; -import 'mocha'; -import { - Call1Dyn, - DecDyn, - DelObjProp, - EqDyn, - Imm, - IncDyn, - Jeqz, - Jmp, - Label, - LdaDyn, - LdaiDyn, - LdaStr, - LdObjByName, - NegDyn, - NotDyn, - ResultType, - ReturnUndefined, - StaDyn, - Toboolean, - Tonumber, - TryLdGlobalByName, - TypeOfDyn, - VReg -} from "../src/irnodes"; -import { checkInstructions, compileMainSnippet, SnippetCompiler } from "./utils/base"; - -describe("UnaryOperationsTest", function() { - describe("PrefixOperationsTest", function() { - it('let i = 5; ++i', function() { - let insns = compileMainSnippet("let i = 5; let j = ++i"); - - let i = new VReg(); - let j = new VReg(); - let temp = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new IncDyn(temp), - new StaDyn(i), - new StaDyn(j), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('let i = 5; --i', function() { - let insns = compileMainSnippet("let i = 5; let j = --i"); - - let i = new VReg(); - let j = new VReg(); - let temp = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new DecDyn(temp), - new StaDyn(i), - new StaDyn(j), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('let i = 5; let j = +i', function() { - let insns = compileMainSnippet("let i = 5; let j = +i"); - - let i = new VReg(); - let j = new VReg(); - let temp = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new Tonumber(temp), - new StaDyn(j), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('let i = 5; let j = -i', function() { - let insns = compileMainSnippet("let i = 5; let j = -i"); - - let i = new VReg(); - let j = new VReg(); - let temp = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new NegDyn(temp), - new StaDyn(j), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('let i = 5; let j = !i', function() { - let insns = compileMainSnippet("let i = 5; let j = !i"); - - let i = new VReg(); - let j = new VReg(); - let trueReg = new VReg(); - let preLabel = new Label(); - let postLabel = new Label(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(new VReg()), - new Toboolean(), - new EqDyn(trueReg), - new Jeqz(preLabel), - new LdaDyn(new VReg()), - new Jmp(postLabel), - preLabel, - new LdaDyn(new VReg()), - postLabel, - new StaDyn(j), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it('let i = 5; let j = ~i', function() { - let insns = compileMainSnippet("let i = 5; let j = ~i"); - - let i = new VReg(); - let j = new VReg(); - let temp_i = new VReg(); - - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp_i), - new NotDyn(temp_i), - new StaDyn(j), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); - - describe("PostfixOperationsTest", function() { - it("let i = 0; i++", function() { - let insns = compileMainSnippet("let i = 5; i++"); - let i = new VReg(); - let temp = new VReg(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new IncDyn(temp), - new StaDyn(i), - new Tonumber(i), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("let i = 0; i--", function() { - let insns = compileMainSnippet("let i = 5; i--"); - let i = new VReg(); - let temp = new VReg(); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new StaDyn(i), - new LdaDyn(i), - new StaDyn(temp), - new DecDyn(temp), - new StaDyn(i), - new Tonumber(i), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); - - describe("TypeOfTest", function() { - it("typeof 12", function() { - let insns = compileMainSnippet("typeof 5"); - let expected = [ - new LdaiDyn(new Imm(ResultType.Int, 5)), - new TypeOfDyn(), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("typeof Number(\"12\")", function() { - let insns = compileMainSnippet("typeof Number(\"5\")"); - let arg1 = new VReg(); - let arg3 = new VReg(); - let expected = [ - new TryLdGlobalByName("Number"), - new StaDyn(arg1), - - new LdaStr("5"), - new StaDyn(arg3), - new Call1Dyn(arg1, arg3), - new TypeOfDyn(), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("typeof x", function() { - let insns = compileMainSnippet("typeof x"); - - let expected = [ - new LdObjByName("x", new VReg()), - new TypeOfDyn(), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("typeof(x)", function() { - let insns = compileMainSnippet("typeof(x)"); - - let expected = [ - new LdObjByName("x", new VReg()), - new TypeOfDyn(), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); - - describe("voidExpressionTest", function() { - it("void (a)", function() { - let insns = compileMainSnippet("let a; void (a);"); - let a = new VReg(); - let expected = [ - new LdaDyn(new VReg()), - new StaDyn(a), - new LdaDyn(a), - new LdaDyn(new VReg()), - new ReturnUndefined() - ]; - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); - - describe("deleteExpressionTest", function() { - it("deleteElementFromArray", function() { - let insns = compileMainSnippet("let arr = [1, 2]; delete arr[1];"); - let arrayReg = new VReg(); - let objReg = new VReg(); - let propReg = new VReg(); - - let expected = [ - // let arr = [1, 2]; - // ... - // delete arr[1]; - new LdaDyn(arrayReg), - new StaDyn(objReg), - new LdaiDyn(new Imm(ResultType.Int, 1)), - new StaDyn(propReg), - new DelObjProp(objReg, propReg), - new ReturnUndefined() - ]; - - insns = insns.slice(insns.length - 6, insns.length); - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("deletePropFromObj", function() { - // this Snippet code isn't supported by TS - let insns = compileMainSnippet(`let obj = { - a: 1, - b: 2}; - delete obj.b;`); - let localObj = new VReg(); - let objReg = new VReg(); - let propReg = new VReg(); - - let expected = [ - // delete obj.b; - new LdaDyn(localObj), - new StaDyn(objReg), - new LdaStr("b"), - new StaDyn(propReg), - new DelObjProp(objReg, propReg), - new ReturnUndefined() - ]; - - insns = insns.slice(insns.length - 6, insns.length); - expect(checkInstructions(insns, expected)).to.be.true; - }); - - // delete function call won't use delObjProp - it("deleteFunctionCall", function() { - let snippetCompiler = new SnippetCompiler(); - snippetCompiler.compile(`var foo = function() { - bIsFooCalled = true; - }; - let a = delete foo();`); - - let insns = snippetCompiler.getGlobalInsns(); - let a = new VReg(); - let expected = [ - // function call insns - new LdaDyn(new VReg()), - new StaDyn(a), - new ReturnUndefined() - ]; - - insns = insns.slice(insns.length - 3, insns.length); - expect(checkInstructions(insns, expected)).to.be.true; - }); - - // delete keywords won't use delObjProp - it("deleteKeywords", function() { - let insns = compileMainSnippet(`let a = delete false;`); - let a = new VReg(); - - let expected = [ - new LdaDyn(new VReg()), - new LdaDyn(new VReg()), - new StaDyn(a), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("deleteUnresolvable", function() { - let insns = compileMainSnippet(`delete a;`); - let globalReg = new VReg(); - let a = new VReg(); - - let expected = [ - new LdaStr("a"), - new StaDyn(a), - new DelObjProp(globalReg, a), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - - it("double delete", function() { - let insns = compileMainSnippet(`delete delete a;`); - let globalReg = new VReg(); - let a = new VReg(); - - let expected = [ - new LdaStr("a"), - new StaDyn(a), - new DelObjProp(globalReg, a), - new LdaDyn(new VReg()), - new ReturnUndefined() - ]; - - expect(checkInstructions(insns, expected)).to.be.true; - }); - }); -}); diff --git a/ts2panda/tests/utils/asthelper.ts b/ts2panda/tests/utils/asthelper.ts index de869a4650..51d5dbb431 100644 --- a/ts2panda/tests/utils/asthelper.ts +++ b/ts2panda/tests/utils/asthelper.ts @@ -23,7 +23,7 @@ export function creatAstFromSnippet(snippet: string): ts.SourceFile { /** It would be tricky here to use relative path, so please use an absolute path instead. * For how to use this function, please refer to example_asthelper.ts - */ + */ export function creatAstFromFile(fileName: string): ts.SourceFile { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES2015, true); return sourceFile; diff --git a/ts2panda/tests/utils/base.ts b/ts2panda/tests/utils/base.ts index b4185ef75d..78718fbd04 100644 --- a/ts2panda/tests/utils/base.ts +++ b/ts2panda/tests/utils/base.ts @@ -28,8 +28,8 @@ import { Pass } from "../../src/pass"; import { Scope } from "../../src/scope"; -import { creatAstFromSnippet } from "./asthelper"; import { setGlobalStrict } from "../../src/strictMode"; +import { creatAstFromSnippet } from "./asthelper"; const compileOptions = { outDir: "../tmp/build", @@ -107,7 +107,6 @@ export function basicChecker(left: IRNode, right: IRNode): boolean { for (let i = 0; i < operandCount; ++i) { const lop = left.operands[i]; const rop = right.operands[i]; - if (!basicOperandsEqual(lop, rop)) { console.log("left.operands:"); console.log(left.operands[i]); diff --git a/ts2panda/ts2abc_config.gni b/ts2panda/ts2abc_config.gni index a86ae8032e..3455351b72 100755 --- a/ts2panda/ts2abc_config.gni +++ b/ts2panda/ts2abc_config.gni @@ -151,3 +151,46 @@ template("ts2abc_gen_abc") { outputs = invoker.out_puts } } + +# ts2abc performs the ut test +# +# Mandatory arguments: +# js_file: The name of the test use case file to execute , ex expression/TemplateExpression.test.js +template("ts2abc_unittest") { + assert(defined(invoker.js_file), "js_file is required!") + + action("$target_name") { + script = "${ts2abc_root}/scripts/run_tests.py" + deps = [ "${ts2abc_root}:ts2abc_tests" ] + + args = [ + "--src-dir", + rebase_path("${ts2abc_root}"), + "--dist-dir", + rebase_path(target_out_dir + "/.."), + "--node-modules", + rebase_path("${node_modules}"), + "--js-file", + invoker.js_file, + "--gn-build", + ] + + if (host_toolchain == buildtool_linux) { + args += [ + "--platform", + "linux", + ] + } else if (host_toolchain == buildtool_mac) { + args += [ + "--platform", + "mac", + ] + } else { + args += [ + "--platform", + "win", + ] + } + outputs = [ "$target_out_dir/${target_name}/" ] + } +} -- Gitee From d0d576dc57d5d77226fe016704cdcd68658eb45c Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 8 Oct 2021 16:19:09 +0800 Subject: [PATCH 25/39] 1. workaround for undefined reference caused by node that neither a parent or a child 2. workaround for getText() error caused by incorrect pos info 3. fix undefined checking error caused by typescript upgrade Signed-off-by: zhuoli Change-Id: I70b6a374fede233bef115b9da8abdb6d0bbc6dd4 --- ts2panda/src/base/typeSystem.ts | 26 ++++++++++++++++-------- ts2panda/src/statement/classStatement.ts | 3 +++ ts2panda/src/syntaxChecker.ts | 8 ++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 712d0c0a16..de145c889b 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -22,6 +22,7 @@ import { import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; import { PandaGen } from "../pandagen"; +import * as jshelpers from "../jshelpers"; export enum PrimitiveType { ANY, @@ -49,12 +50,18 @@ export abstract class BaseType { protected getTypePosForIdentifier(node: ts.Node): number { let identifierSymbol = this.typeChecker.getTypeAtLocation(node).symbol; - return identifierSymbol.declarations[0].pos; + if (identifierSymbol && identifierSymbol.declarations) { + return identifierSymbol.declarations[0].pos; + } + return -1; } protected getTypeNodeForIdentifier(node: ts.Node): ts.Node { let identifierSymbol = this.typeChecker.getTypeAtLocation(node).symbol; - return identifierSymbol.declarations[0]; + if (identifierSymbol && identifierSymbol.declarations) { + return identifierSymbol!.declarations[0]; + } + return node; } protected getTypeFlagsForIdentifier(node: ts.Node): string { @@ -115,12 +122,11 @@ export abstract class BaseType { this.setVariable2Type(variablePos, typeIndex); } if (typeIndex == -1) { - console.log("ERROR: Type cannot be found for: " + node.getText()); + console.log("ERROR: Type cannot be found for: " + jshelpers.getTextOfNode(node)); } return typeIndex!; } - // console.trace(); - console.log("WARNING: node type not found for: " + node.getText()); + console.log("WARNING: node type not found for: " + jshelpers.getTextOfNode(node)); return -1; } @@ -141,7 +147,7 @@ export abstract class BaseType { protected getLog(node: ts.Node, currIndex: number) { console.log("=========== NodeKind ===========: " + node.kind); - console.log(node.getText()); + console.log(jshelpers.getTextOfNode(node)); console.log("=========== currIndex ===========: ", currIndex); console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); console.log("=============================="); @@ -213,7 +219,7 @@ export class ClassType extends BaseType { private fillInFields(member: ts.PropertyDeclaration) { // collect modifier info - let fieldName = member.name.getText(); + let fieldName = jshelpers.getTextOfIdentifierOrLiteral(member.name); let fieldInfo = Array(0, 0, 0, 0); if (member.modifiers) { for (let modifier of member.modifiers) { @@ -320,7 +326,11 @@ export class FunctionType extends BaseType { // in case there's recursive reference of this type this.addCurrentType(funcNode, currIndex); - this.name = funcNode.name ?.getText(); + if (funcNode.name) { + this.name = jshelpers.getTextOfIdentifierOrLiteral(funcNode.name); + } else { + this.name = "constructor"; + } this.fillInModifiers(funcNode); this.fillInParameters(funcNode); this.fillInReturn(funcNode); diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index a694437b44..2478c7abff 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -324,6 +324,9 @@ function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { } let nearestFuncScope = recorder.getScopeOfNode(nearestFunc); + if (!nearestFuncScope) { + return; + } if (ts.isConstructorDeclaration(nearestFunc)) { let funcObj = nearestFuncScope.findLocal("4funcObj"); diff --git a/ts2panda/src/syntaxChecker.ts b/ts2panda/src/syntaxChecker.ts index 185e3a2df3..5f405aa824 100644 --- a/ts2panda/src/syntaxChecker.ts +++ b/ts2panda/src/syntaxChecker.ts @@ -515,7 +515,7 @@ function checkModifiers(node: ts.Node) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "readonly"]); } else if (flags & ts.ModifierFlags.Async) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "async"]); - } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { + } else if (node.parent && (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent))) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, [text]); } else if (flags & ts.ModifierFlags.Abstract) { if (modifier.kind === ts.SyntaxKind.PrivateKeyword) { @@ -536,7 +536,7 @@ function checkModifiers(node: ts.Node) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "readonly"]); } else if (flags & ts.ModifierFlags.Async) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "async"]); - } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { + } else if (node.parent && (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent))) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, ["static"]); } else if (ts.isParameter(node)) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["static"]); @@ -569,7 +569,7 @@ function checkModifiers(node: ts.Node) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "abstract"]); } else if (flags & ts.ModifierFlags.Async) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "async"]); - } else if (ts.isClassLike(node.parent)) { + } else if (node.parent && ts.isClassLike(node.parent)) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["export"]); } else if (ts.isParameter(node)) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["export"]); @@ -591,7 +591,7 @@ function checkModifiers(node: ts.Node) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["declare"]); } else if (flags & ts.ModifierFlags.Async) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_in_an_ambient_context, file, ["async"]); - } else if (ts.isClassLike(node.parent) && !ts.isPropertyDeclaration(node)) { + } else if (node.parent && ts.isClassLike(node.parent) && !ts.isPropertyDeclaration(node)) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["declare"]); } else if (ts.isParameter(node)) { throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["declare"]); -- Gitee From 57c0bf4a945ceeb75db981ff7c0f951bc7f4fc1c Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 8 Oct 2021 21:24:33 +0800 Subject: [PATCH 26/39] Use node as key of typeinfo map instead of node.pos to avoid erroneous pos info after switching to "after" Signed-off-by: zhuoli Change-Id: I0889da3f664486951fbb940baaacea970217f63e --- ts2panda/src/addVariable2Scope.ts | 12 ++--- ts2panda/src/base/typeSystem.ts | 75 +++++++++++++++++-------------- ts2panda/src/index.ts | 1 + ts2panda/src/patch.diff | 60 +++++++++++++++++++++++++ ts2panda/src/typeChecker.ts | 3 +- ts2panda/src/typeRecorder.ts | 33 +++++++------- 6 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 ts2panda/src/patch.diff diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index d98b223193..d4d76492ff 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -42,23 +42,23 @@ import { PrimitiveType } from "./base/typeSystem"; function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(node.pos); + let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(node); if (typeIndex != -1) { v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } - console.log("--node.pos--", node.pos); - console.log("--node.type--", v.getTypeIndex()); + // console.log("--node--", jshelpers.getTextOfNode(node)); + // console.log("--node.type--", v.getTypeIndex()); } } function setClassOrFunctionType(node: ts.Node, v: Variable | undefined) { if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node.pos); + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node); if (typeIndex != -1) { v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } - console.log("--node.pos--", node.pos); - console.log("--node.type--", v.getTypeIndex()); + // console.log("--node--", jshelpers.getTextOfNode(node)); + // console.log("--node.type--", v.getTypeIndex()); } } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index de145c889b..5ca4a5c021 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -70,44 +70,44 @@ export abstract class BaseType { } protected addCurrentType(node: ts.Node, index: number) { - let typePos = node.pos; - this.typeRecorder.addType2Index(typePos, index); + this.typeRecorder.addType2Index(node, index); } - protected setVariable2Type(variablePos: number, index: number) { - this.typeRecorder.setVariable2Type(variablePos, index); + protected setVariable2Type(variableNode: ts.Node, index: number) { + this.typeRecorder.setVariable2Type(variableNode, index); } - protected createType(node: ts.Node, variablePos?: number) { + protected createType(node: ts.Node, variableNode?: ts.Node) { switch (node.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: { - new FunctionType(node, variablePos); + new FunctionType(node, variableNode); break; } case ts.SyntaxKind.ClassDeclaration: { - new ClassType(node, variablePos); + new ClassType(node, variableNode); break; } } } - protected getOrCreateUserDefinedType(node: ts.Node, variablePos?: number) { - let typePos = this.getTypePosForIdentifier(node); - let typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + protected getOrCreateUserDefinedType(node: ts.Node, variableNode?: ts.Node) { + let typeNode = this.getTypeNodeForIdentifier(node); + let typeIndex = this.typeRecorder.tryGetTypeIndex(typeNode); if (typeIndex == -1) { let typeNode = this.getTypeNodeForIdentifier(node); - this.createType(typeNode, variablePos); - typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + this.createType(typeNode, variableNode); + typeIndex = this.typeRecorder.tryGetTypeIndex(typeNode); } return typeIndex; } protected getTypeIndexForDeclWithType( - node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variablePos?: number): number { + node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variableNode?: ts.Node): number { if (node.type) { + // get typeFlag to check if its a primitive type let typeRef = node.type; let typeFlagName = this.getTypeFlagsForIdentifier(typeRef); let typeIndex = -1; @@ -115,11 +115,11 @@ export abstract class BaseType { typeIndex = PrimitiveType[typeFlagName as keyof typeof PrimitiveType]; } else { let identifier = typeRef.getChildAt(0); - typeIndex = this.getOrCreateUserDefinedType(identifier, variablePos); + typeIndex = this.getOrCreateUserDefinedType(identifier, variableNode); } - // set variable if variablePos is given; - if (variablePos) { - this.setVariable2Type(variablePos, typeIndex); + // set variable if variable node is given; + if (variableNode) { + this.setVariable2Type(variableNode, typeIndex); } if (typeIndex == -1) { console.log("ERROR: Type cannot be found for: " + jshelpers.getTextOfNode(node)); @@ -145,14 +145,22 @@ export abstract class BaseType { return currIndex; } + protected printMap(map: Map) { + map.forEach((value, key) =>{ + console.log(jshelpers.getTextOfNode(key) + ": " + value); + }); + } + protected getLog(node: ts.Node, currIndex: number) { console.log("=========== NodeKind ===========: " + node.kind); console.log(jshelpers.getTextOfNode(node)); console.log("=========== currIndex ===========: ", currIndex); console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); console.log("=============================="); - console.log("type2Index: ", this.typeRecorder.getType2Index()); - console.log("variable2Type: ", this.typeRecorder.getVariable2Type()); + console.log("type2Index: "); + console.log(this.printMap(this.typeRecorder.getType2Index())); + console.log("variable2Type: "); + console.log(this.printMap(this.typeRecorder.getVariable2Type())); console.log("=============================="); } } @@ -170,7 +178,7 @@ export class ClassType extends BaseType { fields: Map> = new Map>(); methods: Array = new Array(); - constructor(classNode: ts.ClassDeclaration, variablePos?: number) { + constructor(classNode: ts.ClassDeclaration, variableNode?: ts.Node) { super(); let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); @@ -183,8 +191,8 @@ export class ClassType extends BaseType { this.fillInFieldsAndMethods(classNode); // initialization finished, add variable to type if variable is given - if (variablePos) { - this.setVariable2Type(variablePos, currIndex); + if (variableNode) { + this.setVariable2Type(variableNode, currIndex); } this.setTypeArrayBuffer(this, currIndex); // check typeRecorder @@ -244,8 +252,8 @@ export class ClassType extends BaseType { } } // collect type info - let variablePos = member.name ? member.name.pos : member.pos; - fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variablePos); + let variableNode = member.name ? member.name : undefined; + fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variableNode); this.fields.set(fieldName, fieldInfo); } @@ -259,14 +267,13 @@ export class ClassType extends BaseType { case ts.SyntaxKind.SetAccessor: { // a method like declaration in class must be a new type, // add it into typeRecorder - let typePos = member.pos; - let variablePos = member.name ? member.name.pos : member.pos; - let typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + let variableNode = member.name ? member.name : undefined; + let typeIndex = this.typeRecorder.tryGetTypeIndex(member); if (typeIndex == -1) { - this.createType(member, variablePos) + this.createType(member, variableNode) } // Then, get the typeIndex and fill in the methods array - typeIndex = this.typeRecorder.tryGetTypeIndex(typePos); + typeIndex = this.typeRecorder.tryGetTypeIndex(member); this.methods.push(typeIndex!); break; } @@ -318,7 +325,7 @@ export class FunctionType extends BaseType { parameters: Array = new Array(); returnType: number = 0; - constructor(funcNode: ts.FunctionLikeDeclaration, variablePos?: number) { + constructor(funcNode: ts.FunctionLikeDeclaration, variableNode?: ts.Node) { super(); let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); @@ -336,8 +343,8 @@ export class FunctionType extends BaseType { this.fillInReturn(funcNode); // initialization finished, add variable to type if variable is given - if (variablePos) { - this.setVariable2Type(variablePos, currIndex); + if (variableNode) { + this.setVariable2Type(variableNode, currIndex); } this.setTypeArrayBuffer(this, currIndex); @@ -368,8 +375,8 @@ export class FunctionType extends BaseType { private fillInParameters(node: ts.FunctionLikeDeclaration) { if (node.parameters) { for (let parameter of node.parameters) { - let variableName = parameter.pos; - let typeIndex = this.getTypeIndexForDeclWithType(parameter, variableName); + let variableNode = parameter; + let typeIndex = this.getTypeIndexForDeclWithType(parameter, variableNode); this.parameters.push(typeIndex); } } diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 3eb9fbab54..743502f8bb 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -57,6 +57,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { let newNode = ts.createSourceFile(node.fileName, text, options.target!); node = newNode; } + console.log("----------------------------------- after --------------------------------"); let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); diff --git a/ts2panda/src/patch.diff b/ts2panda/src/patch.diff new file mode 100644 index 0000000000..5c308190ca --- /dev/null +++ b/ts2panda/src/patch.diff @@ -0,0 +1,60 @@ +diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts +index 6d05c0a..2fdd8a1 100644 +--- a/ts2panda/src/debuginfo.ts ++++ b/ts2panda/src/debuginfo.ts +@@ -174,8 +174,25 @@ export class DebugInfo { + if (!file) { + return; + } +- let loc = file.getLineAndCharacterOfPosition(firstStmt.getStart()); +- let wholeLineText = firstStmt.getText(); ++ ++ let pos : number = 0; ++ let tempWholeLineText : string = "" ++ if (firstStmt.pos === -1 || firstStmt.end === -1) { ++ let parent = firstStmt.parent; ++ while (parent) { ++ if (parent.pos !== -1 && parent.end !== -1) { ++ pos = parent.pos; ++ tempWholeLineText = parent.getText(); ++ break; ++ } ++ parent = parent.parent; ++ } ++ } else { ++ pos = firstStmt.getStart(); ++ } ++ ++ let loc = file.getLineAndCharacterOfPosition(pos); ++ let wholeLineText = tempWholeLineText || firstStmt.getText(); + posInfo.setSourecLineNum(loc.line); + posInfo.setSourecColumnNum(loc.character); + posInfo.setWholeLine(wholeLineText); +@@ -206,8 +223,25 @@ export class DebugInfo { + if (!file) { + return; + } +- let loc = file.getLineAndCharacterOfPosition(tsNode.getStart()); +- wholeLineText = tsNode.getText(); ++ ++ let pos : number = 0; ++ let tempWholeLineText : string = "" ++ if (tsNode.pos === -1 || tsNode.end === -1) { ++ let parent = tsNode.parent; ++ while (parent) { ++ if (parent.pos !== -1 && parent.end !== -1) { ++ pos = parent.pos; ++ tempWholeLineText = parent.getText(); ++ break; ++ } ++ parent = parent.parent; ++ } ++ } else { ++ pos = tsNode.getStart(); ++ } ++ ++ let loc = file.getLineAndCharacterOfPosition(pos); ++ wholeLineText = tempWholeLineText || tsNode.getText(); + lineNumber = loc.line; + columnNumber = loc.character; + } diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index d07bd4ce22..62014444ab 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -33,9 +33,8 @@ export class TypeChecker { let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); let targetNode = type.getSymbol()?.valueDeclaration; if (targetNode) { - let variablePos = nameNode.pos; if (ts.isClassDeclaration(targetNode!)) { - let testClassType = new ClassType(targetNode, variablePos); + let testClassType = new ClassType(targetNode, nameNode); } } // console.log(type.getSymbol()?.valueDeclaration); diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index 52b9c18798..a164125bd9 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -13,6 +13,7 @@ * limitations under the License. */ +import ts from "typescript"; import { BaseType, PrimitiveType @@ -20,9 +21,9 @@ import { export class TypeRecorder { private static instance: TypeRecorder; - private type2Index: Map = new Map(); + private type2Index: Map = new Map(); private typeInfo: Array = new Array(); - private variable2Type: Map = new Map(); + private variable2Type: Map = new Map(); // temp for test index public index: number; @@ -39,36 +40,36 @@ export class TypeRecorder { TypeRecorder.instance = new TypeRecorder(); } - public addType2Index(typePosition: number, index: number) { - this.type2Index.set(typePosition, index); + public addType2Index(typeNode: ts.Node, index: number) { + this.type2Index.set(typeNode, index); } - public setVariable2Type(variablePos: number, index: number) { - this.variable2Type.set(variablePos, index); + public setVariable2Type(variableNode: ts.Node, index: number) { + this.variable2Type.set(variableNode, index); } - public hasType(typePosition: number): boolean { - return this.type2Index.has(typePosition); + public hasType(typeNode: ts.Node): boolean { + return this.type2Index.has(typeNode); } - public tryGetTypeIndex(typePosition: number): number { - if (this.type2Index.has(typePosition)) { - return this.type2Index.get(typePosition)!; + public tryGetTypeIndex(typeNode: ts.Node): number { + if (this.type2Index.has(typeNode)) { + return this.type2Index.get(typeNode)!; } else { return -1; } } - public tryGetVariable2Type(variablePosition: number): number { - if (this.variable2Type.has(variablePosition)) { - return this.variable2Type.get(variablePosition)!; + public tryGetVariable2Type(variableNode: ts.Node): number { + if (this.variable2Type.has(variableNode)) { + return this.variable2Type.get(variableNode)!; } else { return -1; } } // might not needed - public getType2Index(): Map { + public getType2Index(): Map { return this.type2Index; } @@ -76,7 +77,7 @@ export class TypeRecorder { return this.typeInfo; } - public getVariable2Type(): Map { + public getVariable2Type(): Map { return this.variable2Type; } } \ No newline at end of file -- Gitee From 9c8fd93047010ff8234aacaf32253e6ec3ec72a5 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Fri, 8 Oct 2021 21:26:17 +0800 Subject: [PATCH 27/39] setTextRange is causing incorrect pos info. Disable temporarily as a workaround. Signed-off-by: zhuoli Change-Id: I1b20e0b2f07e369254c556b002b1bfc5bba97e68 --- ts2panda/src/debuginfo.ts | 44 ++++++++++++++++++++++++++++++++++----- ts2panda/src/recorder.ts | 2 +- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index 6d05c0aa04..688eac267e 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -174,8 +174,25 @@ export class DebugInfo { if (!file) { return; } - let loc = file.getLineAndCharacterOfPosition(firstStmt.getStart()); - let wholeLineText = firstStmt.getText(); + + let pos : number = 0; + let tempWholeLineText : string = "" + if (firstStmt.pos === -1 || firstStmt.end === -1) { + let parent = firstStmt.parent; + while (parent) { + if (parent.pos !== -1 && parent.end !== -1) { + pos = parent.pos; + tempWholeLineText = parent.getText(); + break; + } + parent = parent.parent; + } + } else { + pos = firstStmt.getStart(); + } + + let loc = file.getLineAndCharacterOfPosition(pos); + let wholeLineText = tempWholeLineText || firstStmt.getText(); posInfo.setSourecLineNum(loc.line); posInfo.setSourecColumnNum(loc.character); posInfo.setWholeLine(wholeLineText); @@ -206,8 +223,25 @@ export class DebugInfo { if (!file) { return; } - let loc = file.getLineAndCharacterOfPosition(tsNode.getStart()); - wholeLineText = tsNode.getText(); + + let pos : number = 0; + let tempWholeLineText : string = "" + if (tsNode.pos === -1 || tsNode.end === -1) { + let parent = tsNode.parent; + while (parent) { + if (parent.pos !== -1 && parent.end !== -1) { + pos = parent.pos; + tempWholeLineText = parent.getText(); + break; + } + parent = parent.parent; + } + } else { + pos = tsNode.getStart(); + } + + let loc = file.getLineAndCharacterOfPosition(pos); + wholeLineText = tempWholeLineText || tsNode.getText(); lineNumber = loc.line; columnNumber = loc.character; } @@ -384,4 +418,4 @@ export class DebugInfo { scope.setScopeEndIns(placeHolder); } } -} \ No newline at end of file +} diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index b3dff77484..e461ee9d47 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -84,7 +84,7 @@ export class Recorder { node.forEachChild(childNode => { if (childNode!.parent == undefined || childNode.parent.kind != node.kind) { childNode = jshelpers.setParent(childNode, node)!; - childNode = ts.setTextRange(childNode, node)!; + // childNode = ts.setTextRange(childNode, node)!; } checkSyntaxError(childNode); switch (childNode.kind) { -- Gitee From dabbb864620fea3903705336f1d6383607e020ba Mon Sep 17 00:00:00 2001 From: ctw Date: Sat, 9 Oct 2021 16:45:14 +0800 Subject: [PATCH 28/39] seperate static unstatic fields Signed-off-by: ctw Change-Id: I13fe06a302e67a3562712d2c18b459b5906187dd --- ts2panda/src/base/typeSystem.ts | 80 ++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 5ca4a5c021..62c3237fb7 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -90,6 +90,9 @@ export abstract class BaseType { new ClassType(node, variableNode); break; } + // create other type as project goes on; + default: + throw new Error("Currently this type is not supported"); } } @@ -146,7 +149,7 @@ export abstract class BaseType { } protected printMap(map: Map) { - map.forEach((value, key) =>{ + map.forEach((value, key) => { console.log(jshelpers.getTextOfNode(key) + ": " + value); }); } @@ -174,7 +177,9 @@ export class PlaceHolderType extends BaseType { export class ClassType extends BaseType { modifier: number = 0; // 0 -> unabstract, 1 -> abstract; heritages: Array = new Array(); - // fileds Array: [typeIndex] [static -> 1] [public -> 0, private -> 1, protected -> 2] [readonly -> 1] + // fileds Array: [typeIndex] [public -> 0, private -> 1, protected -> 2] [readonly -> 1] + staticFields: Map> = new Map>(); + staticMethods: Array = new Array(); fields: Map> = new Map>(); methods: Array = new Array(); @@ -227,25 +232,39 @@ export class ClassType extends BaseType { private fillInFields(member: ts.PropertyDeclaration) { // collect modifier info - let fieldName = jshelpers.getTextOfIdentifierOrLiteral(member.name); - let fieldInfo = Array(0, 0, 0, 0); + let fieldName: string = ""; + switch (member.name.kind) { + case ts.SyntaxKind.Identifier: + case ts.SyntaxKind.StringLiteral: + case ts.SyntaxKind.NumericLiteral: + fieldName = jshelpers.getTextOfIdentifierOrLiteral(member.name); + break; + case ts.SyntaxKind.ComputedPropertyName: + fieldName = "#computed"; + break; + default: + throw new Error("Invalid proerty name"); + } + + let fieldInfo = Array(0, 0, 0); + let isStatic: boolean = false; if (member.modifiers) { for (let modifier of member.modifiers) { switch (modifier.kind) { case ts.SyntaxKind.StaticKeyword: { - fieldInfo[1] = 1; + isStatic = true; break; } case ts.SyntaxKind.PrivateKeyword: { - fieldInfo[2] = 1; + fieldInfo[1] = 1; break; } case ts.SyntaxKind.ProtectedKeyword: { - fieldInfo[2] = 2; + fieldInfo[1] = 2; break; } case ts.SyntaxKind.ReadonlyKeyword: { - fieldInfo[3] = 1; + fieldInfo[2] = 1; break; } } @@ -254,7 +273,12 @@ export class ClassType extends BaseType { // collect type info let variableNode = member.name ? member.name : undefined; fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variableNode); - this.fields.set(fieldName, fieldInfo); + + if (isStatic) { + this.staticFields.set(fieldName, fieldInfo); + } else { + this.fields.set(fieldName, fieldInfo); + } } private fillInFieldsAndMethods(node: ts.ClassDeclaration) { @@ -265,12 +289,14 @@ export class ClassType extends BaseType { case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: { - // a method like declaration in class must be a new type, - // add it into typeRecorder + /** + * a method like declaration in class must be a new type, + * add it into typeRecorder + */ let variableNode = member.name ? member.name : undefined; let typeIndex = this.typeRecorder.tryGetTypeIndex(member); if (typeIndex == -1) { - this.createType(member, variableNode) + this.createType(member, variableNode); } // Then, get the typeIndex and fill in the methods array typeIndex = this.typeRecorder.tryGetTypeIndex(member); @@ -293,21 +319,20 @@ export class ClassType extends BaseType { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASS)); classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); // num of heritages are recorded + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.heritages.length)); this.heritages.forEach(heritage => { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); }); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.fields.size)); // num of fields are recorded - this.fields.forEach((typeInfo, name) => { - classTypeLiterals.push(new Literal(LiteralTag.STRING, name)); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[0])); // typeIndex - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[1])); // static - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); // accessFlag - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[3])); // readonly - }); + // record static methods and fields; + this.transferFields2Literal(classTypeLiterals, true); + + // TODO record static methods here + + // record unstatic fields and methods + this.transferFields2Literal(classTypeLiterals, false); - classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); // num of fields are recorded + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.methods.length)); this.methods.forEach(method => { classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); }); @@ -316,6 +341,17 @@ export class ClassType extends BaseType { return classTypeBuf; } + private transferFields2Literal(classTypeLiterals: Array, isStatic: boolean) { + let transferredTarget: Map> = isStatic ? this.staticFields : this.fields; + + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, transferredTarget.size)); + transferredTarget.forEach((typeInfo, name) => { + classTypeLiterals.push(new Literal(LiteralTag.STRING, name)); + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[0])); // typeIndex + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[1])); // accessFlag + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, typeInfo[2])); // readonly + }); + } } export class FunctionType extends BaseType { -- Gitee From 29e624003596eb507e5167278ab02e38b695fa42 Mon Sep 17 00:00:00 2001 From: ctw Date: Tue, 12 Oct 2021 11:24:54 +0800 Subject: [PATCH 29/39] add classInstType and seperate static method of class Signed-off-by: ctw Change-Id: I5f57be0bbe8c11b87f7a7891012c35a871b23c2c --- ts2panda/src/base/typeSystem.ts | 71 +++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 62c3237fb7..a8596cc10d 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -38,10 +38,13 @@ export enum PrimitiveType { export enum L2Type { CLASS, + CLASSINST, FUNCTION, OBJECT // object literal } +type ClassMemberFunction = ts.MethodDeclaration | ts.ConstructorDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration; + export abstract class BaseType { abstract transfer2LiteralBuffer(): LiteralBuffer; @@ -77,23 +80,26 @@ export abstract class BaseType { this.typeRecorder.setVariable2Type(variableNode, index); } - protected createType(node: ts.Node, variableNode?: ts.Node) { + protected createType(node: ts.Node, variableNode?: ts.Node): BaseType { + let type: BaseType; switch (node.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: { - new FunctionType(node, variableNode); + type = new FunctionType(node, variableNode); break; } case ts.SyntaxKind.ClassDeclaration: { - new ClassType(node, variableNode); + type = new ClassType(node, variableNode); break; } // create other type as project goes on; default: throw new Error("Currently this type is not supported"); } + + return type; } protected getOrCreateUserDefinedType(node: ts.Node, variableNode?: ts.Node) { @@ -281,6 +287,29 @@ export class ClassType extends BaseType { } } + private fillInMethods(member: ClassMemberFunction) { + /** + * a method like declaration in class must be a new type, + * add it into typeRecorder + */ + let funcType: FunctionType; + let variableNode = member.name ? member.name : undefined; + let typeIndex = this.typeRecorder.tryGetTypeIndex(member); + if (typeIndex == -1) { + funcType = this.createType(member, variableNode); + } + + // Then, get the typeIndex and fill in the methods array + typeIndex = this.typeRecorder.tryGetTypeIndex(member); + funcType = this.typeRecorder.getTypeInfo()[typeIndex]; + let funcModifier = funcType.getModifier(); + if (funcModifier) { + this.staticMethods.push(typeIndex!); + } else { + this.methods.push(typeIndex!); + } + } + private fillInFieldsAndMethods(node: ts.ClassDeclaration) { if (node.members) { for (let member of node.members) { @@ -289,18 +318,7 @@ export class ClassType extends BaseType { case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: { - /** - * a method like declaration in class must be a new type, - * add it into typeRecorder - */ - let variableNode = member.name ? member.name : undefined; - let typeIndex = this.typeRecorder.tryGetTypeIndex(member); - if (typeIndex == -1) { - this.createType(member, variableNode); - } - // Then, get the typeIndex and fill in the methods array - typeIndex = this.typeRecorder.tryGetTypeIndex(member); - this.methods.push(typeIndex!); + this.fillInMethods(member); break; } case ts.SyntaxKind.PropertyDeclaration: { @@ -354,6 +372,24 @@ export class ClassType extends BaseType { } } +export class ClassInstType extends BaseType { + referredClassIndex: number = 0; // the referred class in the type system; + constructor(referredClassIndex: number) { + super(); + this.referredClassIndex = referredClassIndex; + } + + transfer2LiteralBuffer(): LiteralBuffer { + let classInstBuf = new LiteralBuffer(); + let classInstLiterals: Array = new Array(); + classInstLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASSINST)); + classInstLiterals.push(new Literal(LiteralTag.INTEGER, this.referredClassIndex)); + classInstBuf.addLiterals(...classInstLiterals); + + return classInstBuf; + } +} + export class FunctionType extends BaseType { name: string | undefined = ''; accessFlag: number = 0; // 0 -> public -> 0, private -> 1, protected -> 2 @@ -425,12 +461,15 @@ export class FunctionType extends BaseType { } } + getModifier() { + return this.modifier; + } + transfer2LiteralBuffer(): LiteralBuffer { let funcTypeBuf = new LiteralBuffer(); let funcTypeLiterals: Array = new Array(); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.FUNCTION)); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifier)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); -- Gitee From b440b198e238db1dca1a3116d01a909123ae222c Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 12 Oct 2021 15:28:54 +0800 Subject: [PATCH 30/39] 1. Remove use of deval numbers 2. Remove deprecated index counter from typeRecorder Signed-off-by: zhuoli Change-Id: I201532499f979ef9ad7deaa3a7dc4564402b3f4c --- ts2panda/src/base/typeSystem.ts | 49 ++++++++++++++++++++++----------- ts2panda/src/typeRecorder.ts | 7 +---- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index a8596cc10d..d8acc21f22 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -23,6 +23,7 @@ import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; import { PandaGen } from "../pandagen"; import * as jshelpers from "../jshelpers"; +import { access } from "fs"; export enum PrimitiveType { ANY, @@ -43,6 +44,27 @@ export enum L2Type { OBJECT // object literal } +export enum ModifierAbstract { + NONABSTRACT, + ABSTRACT +} + +export enum ModifierStatic { + NONSTATIC, + STATIC +} + +export enum ModifierReadonly { + NONREADONLY, + READONLY +} + +export enum AccessFlag { + PUBLIC, + PRIVATE, + PROTECTED +} + type ClassMemberFunction = ts.MethodDeclaration | ts.ConstructorDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration; export abstract class BaseType { @@ -148,11 +170,6 @@ export abstract class BaseType { } // temp for test - protected getIndex() { - let currIndex = this.typeRecorder.index; - this.typeRecorder.index += 1; - return currIndex; - } protected printMap(map: Map) { map.forEach((value, key) => { @@ -215,7 +232,7 @@ export class ClassType extends BaseType { for (let modifier of node.modifiers) { switch (modifier.kind) { case ts.SyntaxKind.AbstractKeyword: { - this.modifier = 1; + this.modifier = ModifierAbstract.ABSTRACT; break; } case ts.SyntaxKind.ExportKeyword: { @@ -252,7 +269,8 @@ export class ClassType extends BaseType { throw new Error("Invalid proerty name"); } - let fieldInfo = Array(0, 0, 0); + // Array: [typeIndex] [public -> 0, private -> 1, protected -> 2] [readonly -> 1] + let fieldInfo = Array(PrimitiveType.ANY, AccessFlag.PUBLIC, ModifierReadonly.NONREADONLY); let isStatic: boolean = false; if (member.modifiers) { for (let modifier of member.modifiers) { @@ -262,15 +280,15 @@ export class ClassType extends BaseType { break; } case ts.SyntaxKind.PrivateKeyword: { - fieldInfo[1] = 1; + fieldInfo[1] = AccessFlag.PRIVATE; break; } case ts.SyntaxKind.ProtectedKeyword: { - fieldInfo[1] = 2; + fieldInfo[1] = AccessFlag.PROTECTED; break; } case ts.SyntaxKind.ReadonlyKeyword: { - fieldInfo[2] = 1; + fieldInfo[2] = ModifierReadonly.READONLY; break; } } @@ -393,7 +411,7 @@ export class ClassInstType extends BaseType { export class FunctionType extends BaseType { name: string | undefined = ''; accessFlag: number = 0; // 0 -> public -> 0, private -> 1, protected -> 2 - modifier: number = 0; // 0 -> unstatic, 1 -> static + modifierStatic: number = 0; // 0 -> unstatic, 1 -> static parameters: Array = new Array(); returnType: number = 0; @@ -429,15 +447,15 @@ export class FunctionType extends BaseType { for (let modifier of node.modifiers) { switch (modifier.kind) { case ts.SyntaxKind.PrivateKeyword: { - this.accessFlag = 1; + this.accessFlag = AccessFlag.PRIVATE; break; } case ts.SyntaxKind.ProtectedKeyword: { - this.accessFlag = 2; + this.accessFlag = AccessFlag.PROTECTED; break; } case ts.SyntaxKind.StaticKeyword: { - this.modifier = 1; + this.modifierStatic = ModifierStatic.STATIC; } } } @@ -462,7 +480,7 @@ export class FunctionType extends BaseType { } getModifier() { - return this.modifier; + return this.modifierStatic; } transfer2LiteralBuffer(): LiteralBuffer { @@ -471,7 +489,6 @@ export class FunctionType extends BaseType { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.FUNCTION)); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); this.parameters.forEach((type) => { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index a164125bd9..53130340a2 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -25,12 +25,7 @@ export class TypeRecorder { private typeInfo: Array = new Array(); private variable2Type: Map = new Map(); - // temp for test index - public index: number; - - private constructor() { - this.index = PrimitiveType._LENGTH; - } + private constructor() {} public static getInstance() { return TypeRecorder.instance; -- Gitee From 59a345975c1db6c38ca64c77d5aea96d7557fafe Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 12 Oct 2021 15:53:18 +0800 Subject: [PATCH 31/39] Fix empty incorrectly acquired funcType Signed-off-by: zhuoli Change-Id: I2defdd974edf2e4499d3b39b90483da87c3b9657 --- ts2panda/src/base/typeSystem.ts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index d8acc21f22..af07fc6643 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -102,26 +102,23 @@ export abstract class BaseType { this.typeRecorder.setVariable2Type(variableNode, index); } - protected createType(node: ts.Node, variableNode?: ts.Node): BaseType { - let type: BaseType; + protected createType(node: ts.Node, variableNode?: ts.Node) { switch (node.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: { - type = new FunctionType(node, variableNode); + new FunctionType(node, variableNode); break; } case ts.SyntaxKind.ClassDeclaration: { - type = new ClassType(node, variableNode); + new ClassType(node, variableNode); break; } // create other type as project goes on; default: - throw new Error("Currently this type is not supported"); + // throw new Error("Currently this type is not supported"); } - - return type; } protected getOrCreateUserDefinedType(node: ts.Node, variableNode?: ts.Node) { @@ -307,19 +304,14 @@ export class ClassType extends BaseType { private fillInMethods(member: ClassMemberFunction) { /** - * a method like declaration in class must be a new type, - * add it into typeRecorder + * a method like declaration in a new class must be a new type, + * create this type and add it into typeRecorder */ - let funcType: FunctionType; let variableNode = member.name ? member.name : undefined; - let typeIndex = this.typeRecorder.tryGetTypeIndex(member); - if (typeIndex == -1) { - funcType = this.createType(member, variableNode); - } + let funcType = new FunctionType(member, variableNode); // Then, get the typeIndex and fill in the methods array - typeIndex = this.typeRecorder.tryGetTypeIndex(member); - funcType = this.typeRecorder.getTypeInfo()[typeIndex]; + let typeIndex = this.typeRecorder.tryGetTypeIndex(member); let funcModifier = funcType.getModifier(); if (funcModifier) { this.staticMethods.push(typeIndex!); -- Gitee From a905328c3470b97144055403fd75e53b6c62e57a Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 12 Oct 2021 19:00:10 +0800 Subject: [PATCH 32/39] Separate class and its instance as different type Signed-off-by: zhuoli Change-Id: I393dc34864f3815b23e633bb5bc0aacb59e2cb16 --- ts2panda/src/addVariable2Scope.ts | 5 ++--- ts2panda/src/base/typeSystem.ts | 37 ++++++++++++++++++++++--------- ts2panda/src/typeChecker.ts | 6 ++++- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index d4d76492ff..ece905bebf 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -39,7 +39,6 @@ import { import { TypeRecorder } from "./typeRecorder"; import { PrimitiveType } from "./base/typeSystem"; - function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { if (v) { let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(node); @@ -53,11 +52,11 @@ function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { function setClassOrFunctionType(node: ts.Node, v: Variable | undefined) { if (v) { - let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(node); + let typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(ts.getOriginalNode(node)); if (typeIndex != -1) { v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } - // console.log("--node--", jshelpers.getTextOfNode(node)); + // console.log("--node--", jshelpers.getTextOfNode(ts.getOriginalNode(node))); // console.log("--node.type--", v.getTypeIndex()); } } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index af07fc6643..150cd0b0b6 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -102,7 +102,7 @@ export abstract class BaseType { this.typeRecorder.setVariable2Type(variableNode, index); } - protected createType(node: ts.Node, variableNode?: ts.Node) { + protected createType(node: ts.Node, newExpressionFlag: boolean, variableNode?: ts.Node) { switch (node.kind) { case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.Constructor: @@ -112,21 +112,22 @@ export abstract class BaseType { break; } case ts.SyntaxKind.ClassDeclaration: { - new ClassType(node, variableNode); + new ClassType(node, newExpressionFlag, variableNode); break; } // create other type as project goes on; default: + console.log("Error: Currently this type is not supported"); // throw new Error("Currently this type is not supported"); } } - protected getOrCreateUserDefinedType(node: ts.Node, variableNode?: ts.Node) { + protected getOrCreateUserDefinedType(node: ts.Node, newExpressionFlag: boolean, variableNode?: ts.Node) { let typeNode = this.getTypeNodeForIdentifier(node); let typeIndex = this.typeRecorder.tryGetTypeIndex(typeNode); if (typeIndex == -1) { let typeNode = this.getTypeNodeForIdentifier(node); - this.createType(typeNode, variableNode); + this.createType(typeNode, newExpressionFlag, variableNode); typeIndex = this.typeRecorder.tryGetTypeIndex(typeNode); } return typeIndex; @@ -135,6 +136,11 @@ export abstract class BaseType { protected getTypeIndexForDeclWithType( node: ts.FunctionLikeDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration, variableNode?: ts.Node): number { if (node.type) { + // check for newExpression + let newExpressionFlag = false; + if (node.kind == ts.SyntaxKind.PropertyDeclaration && node.initializer && node.initializer.kind == ts.SyntaxKind.NewExpression) { + newExpressionFlag = true; + } // get typeFlag to check if its a primitive type let typeRef = node.type; let typeFlagName = this.getTypeFlagsForIdentifier(typeRef); @@ -143,7 +149,7 @@ export abstract class BaseType { typeIndex = PrimitiveType[typeFlagName as keyof typeof PrimitiveType]; } else { let identifier = typeRef.getChildAt(0); - typeIndex = this.getOrCreateUserDefinedType(identifier, variableNode); + typeIndex = this.getOrCreateUserDefinedType(identifier, newExpressionFlag, variableNode); } // set variable if variable node is given; if (variableNode) { @@ -159,7 +165,7 @@ export abstract class BaseType { } protected getIndexFromTypeArrayBuffer(type: BaseType): number { - return PandaGen.appendTypeArrayBuffer(new PlaceHolderType); + return PandaGen.appendTypeArrayBuffer(type); } protected setTypeArrayBuffer(type: BaseType, index: number) { @@ -203,7 +209,7 @@ export class ClassType extends BaseType { fields: Map> = new Map>(); methods: Array = new Array(); - constructor(classNode: ts.ClassDeclaration, variableNode?: ts.Node) { + constructor(classNode: ts.ClassDeclaration, newExpressionFlag: boolean, variableNode?: ts.Node) { super(); let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); @@ -217,7 +223,12 @@ export class ClassType extends BaseType { // initialization finished, add variable to type if variable is given if (variableNode) { - this.setVariable2Type(variableNode, currIndex); + // if the variable is a instance, create another classInstType instead of current classType itself + if (newExpressionFlag) { + new ClassInstType(variableNode, currIndex); + } else { + this.setVariable2Type(variableNode, currIndex); + } } this.setTypeArrayBuffer(this, currIndex); // check typeRecorder @@ -244,7 +255,7 @@ export class ClassType extends BaseType { if (node.heritageClauses) { for (let heritage of node.heritageClauses) { let heritageIdentifier = heritage.getChildAt(1).getChildAt(0); - let heritageTypePos = this.getOrCreateUserDefinedType(heritageIdentifier); + let heritageTypePos = this.getOrCreateUserDefinedType(heritageIdentifier, false); this.heritages.push(heritageTypePos); } } @@ -384,9 +395,15 @@ export class ClassType extends BaseType { export class ClassInstType extends BaseType { referredClassIndex: number = 0; // the referred class in the type system; - constructor(referredClassIndex: number) { + constructor(variableNode: ts.Node, referredClassIndex: number) { super(); + // use referedClassIndex to point to the actually class type of this instance this.referredClassIndex = referredClassIndex; + + // map variable to classInstType, which has a newly generated index + let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + this.setVariable2Type(variableNode, currIndex); + this.setTypeArrayBuffer(this, currIndex); } transfer2LiteralBuffer(): LiteralBuffer { diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index 62014444ab..6b10ad7a98 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -30,11 +30,15 @@ export class TypeChecker { const decList = variableStatementNode.declarationList; decList.declarations.forEach(declaration => { const nameNode = declaration.name; + let newExpressionFlag = false; + if (declaration.initializer && declaration.initializer.kind == ts.SyntaxKind.NewExpression) { + newExpressionFlag = true; + } let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); let targetNode = type.getSymbol()?.valueDeclaration; if (targetNode) { if (ts.isClassDeclaration(targetNode!)) { - let testClassType = new ClassType(targetNode, nameNode); + let testClassType = new ClassType(targetNode, newExpressionFlag, nameNode); } } // console.log(type.getSymbol()?.valueDeclaration); -- Gitee From 44c1d3c7e4508839ff045dff6de7c3aa411f13cf Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Wed, 13 Oct 2021 10:44:49 +0800 Subject: [PATCH 33/39] =?UTF-8?q?ets=E6=89=93hap=E5=8C=85=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgy-ian --- ts2panda/src/addVariable2Scope.ts | 24 ++++++++++++------------ ts2panda/src/assemblyDumper.ts | 4 ++-- ts2panda/src/base/typeSystem.ts | 26 +++++++++++++------------- ts2panda/src/base/util.ts | 9 +++++++++ ts2panda/src/compilerDriver.ts | 8 ++++---- ts2panda/src/index.ts | 10 ++++++++-- ts2panda/src/recorder.ts | 16 +++++++++++++--- ts2panda/src/ts2panda.ts | 10 +++++----- ts2panda/src/typeChecker.ts | 2 +- ts2panda/src/variable.ts | 4 ++-- 10 files changed, 69 insertions(+), 44 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index d4d76492ff..22bdfe94d4 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -46,8 +46,8 @@ function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { if (typeIndex != -1) { v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } - // console.log("--node--", jshelpers.getTextOfNode(node)); - // console.log("--node.type--", v.getTypeIndex()); + // // console.log("--node--", jshelpers.getTextOfNode(node)); + // // console.log("--node.type--", v.getTypeIndex()); } } @@ -57,8 +57,8 @@ function setClassOrFunctionType(node: ts.Node, v: Variable | undefined) { if (typeIndex != -1) { v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); } - // console.log("--node--", jshelpers.getTextOfNode(node)); - // console.log("--node.type--", v.getTypeIndex()); + // // console.log("--node--", jshelpers.getTextOfNode(node)); + // // console.log("--node.type--", v.getTypeIndex()); } } @@ -107,8 +107,8 @@ export function addVariableToScope(recorder: Recorder) { hoistDecls = hoistMap.get(scope); if (hoistDecls) { hoistDecls.forEach(hoistDecl => { - console.log("/////// hoist pos ////////// - "); - console.log(hoistDecl.node.pos); + // console.log("/////// hoist pos ////////// - "); + // console.log(hoistDecl.node.pos); let v: Variable | undefined; if (hoistDecl instanceof VarDecl) { v = scope.add(hoistDecl.name, VarDeclarationKind.VAR); @@ -132,8 +132,8 @@ export function addVariableToScope(recorder: Recorder) { if (hoistDecls && hoistDecls.includes(decl)) { continue; } - console.log("/////// decls pos ////////// - "); - console.log(decl.node.pos); + // console.log("/////// decls pos ////////// - "); + // console.log(decl.node.pos); let v: Variable | undefined; if (decl instanceof LetDecl) { v = scope.add(decl.name, VarDeclarationKind.LET, InitStatus.UNINITIALIZED); @@ -178,8 +178,8 @@ export function addVariableToScope(recorder: Recorder) { } function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): void { - console.log("////////// methods //////////"); - console.log(node.pos); + // console.log("////////// methods //////////"); + // console.log(node.pos); let patternParams: Array = new Array(); for (let i = 0; i < node.parameters.length; ++i) { let param = node.parameters[i]; @@ -190,8 +190,8 @@ function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): } else if (ts.isIdentifier(param.name)) { name = jshelpers.getTextOfIdentifierOrLiteral(param.name); } - console.log("//////// add para /////////"); - console.log(param.pos); + // console.log("//////// add para /////////"); + // console.log(param.pos); let v = scope.addParameter(name, VarDeclarationKind.VAR, i + 1); setVariableOrParameterType(param, v); diff --git a/ts2panda/src/assemblyDumper.ts b/ts2panda/src/assemblyDumper.ts index c425d876fd..17892d5316 100644 --- a/ts2panda/src/assemblyDumper.ts +++ b/ts2panda/src/assemblyDumper.ts @@ -188,12 +188,12 @@ export class AssemblyDumper { this.writeFunctionCatchTable(); this.writeFunctionTail(); - console.log(this.output); + // console.log(this.output); } static dumpHeader(): void { let out = { str: "" }; AssemblyDumper.writeLanguageTag(out); - console.log(out.str) + // console.log(out.str) } } diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index a8596cc10d..494fc4bebe 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -131,11 +131,11 @@ export abstract class BaseType { this.setVariable2Type(variableNode, typeIndex); } if (typeIndex == -1) { - console.log("ERROR: Type cannot be found for: " + jshelpers.getTextOfNode(node)); + // console.log("ERROR: Type cannot be found for: " + jshelpers.getTextOfNode(node)); } return typeIndex!; } - console.log("WARNING: node type not found for: " + jshelpers.getTextOfNode(node)); + // console.log("WARNING: node type not found for: " + jshelpers.getTextOfNode(node)); return -1; } @@ -156,21 +156,21 @@ export abstract class BaseType { protected printMap(map: Map) { map.forEach((value, key) => { - console.log(jshelpers.getTextOfNode(key) + ": " + value); + // console.log(jshelpers.getTextOfNode(key) + ": " + value); }); } protected getLog(node: ts.Node, currIndex: number) { - console.log("=========== NodeKind ===========: " + node.kind); - console.log(jshelpers.getTextOfNode(node)); - console.log("=========== currIndex ===========: ", currIndex); - console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); - console.log("=============================="); - console.log("type2Index: "); - console.log(this.printMap(this.typeRecorder.getType2Index())); - console.log("variable2Type: "); - console.log(this.printMap(this.typeRecorder.getVariable2Type())); - console.log("=============================="); + // console.log("=========== NodeKind ===========: " + node.kind); + // console.log(jshelpers.getTextOfNode(node)); + // console.log("=========== currIndex ===========: ", currIndex); + // console.log(PandaGen.getLiteralArrayBuffer()[currIndex]); + // console.log("=============================="); + // console.log("type2Index: "); + // console.log(this.printMap(this.typeRecorder.getType2Index())); + // console.log("variable2Type: "); + // console.log(this.printMap(this.typeRecorder.getVariable2Type())); + // console.log("=============================="); } } diff --git a/ts2panda/src/base/util.ts b/ts2panda/src/base/util.ts index c9a2177cad..0d89ae3f55 100755 --- a/ts2panda/src/base/util.ts +++ b/ts2panda/src/base/util.ts @@ -296,3 +296,12 @@ export function getRangeStartVregPos(ins: IRNode): number { } return ins instanceof EcmaCreateobjectwithexcludedkeys ? 2 : 1; } + +let isBeforeCompileFlag : boolean = false; +export function isBeforeCompile():boolean { + return isBeforeCompileFlag; +} + +export function setBeforeCompileFlag(flag: boolean){ + isBeforeCompileFlag = flag; +} \ No newline at end of file diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index 087cbcd304..eac76181cb 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -144,7 +144,9 @@ export class CompilerDriver { } compileForSyntaxCheck(node: ts.SourceFile): void { - this.compilePrologue(node); + let recorder = this.compilePrologue(node); + checkDuplicateDeclaration(recorder); + checkExportEntries(recorder); } compile(node: ts.SourceFile): void { @@ -275,9 +277,7 @@ export class CompilerDriver { let recorder = new Recorder(node, topLevelScope, this); recorder.record(); - - checkDuplicateDeclaration(recorder); - checkExportEntries(recorder); + addVariableToScope(recorder); let postOrderVariableScopes = this.postOrderAnalysis(topLevelScope); diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 743502f8bb..1609a488dd 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -26,6 +26,7 @@ import { setGlobalStrict } from "./strictMode"; import jshelpers = require("./jshelpers"); import { TypeChecker } from "./typeChecker"; import { TypeRecorder } from "./typeRecorder"; +import {setBeforeCompileFlag} from "./base/util"; function main(fileNames: string[], options: ts.CompilerOptions) { let program = ts.createProgram(fileNames, options); @@ -41,6 +42,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { before: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { + setBeforeCompileFlag(true); let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); compilerDriver.compileForSyntaxCheck(node); @@ -51,13 +53,15 @@ function main(fileNames: string[], options: ts.CompilerOptions) { after: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { + setBeforeCompileFlag(false); + let nodeBak = node; if (ts.getEmitHelpers(node)) { const printer: ts.Printer = ts.createPrinter({newLine:ts.NewLineKind.LineFeed}); const text: string = printer.printNode(ts.EmitHint.Unspecified, node, node); let newNode = ts.createSourceFile(node.fileName, text, options.target!); node = newNode; } - console.log("----------------------------------- after --------------------------------"); + // console.log("----------------------------------- after --------------------------------"); let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); @@ -72,7 +76,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { } compilerDriver.compile(node); compilerDriver.showStatistics(); - return node; + return nodeBak; } } ] @@ -128,7 +132,9 @@ function run(args: string[], options?: ts.CompilerOptions): void { main(parsed.fileNames, parsed.options); } catch (err) { if (err instanceof diag.DiagnosticError) { + let diagnostic = diag.getDiagnostic(err.code); + console.log(diagnostic) if (diagnostic != undefined) { let diagnosticLog = diag.createDiagnostic(err.file, err.irnode, diagnostic, ...err.args); diag.printDiagnostic(diagnosticLog); diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index e461ee9d47..918a7a0c7d 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -48,6 +48,7 @@ import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; import { TypeChecker } from "./typeChecker"; +import {isBeforeCompile} from "./base/util"; export class Recorder { node: ts.Node; @@ -71,6 +72,7 @@ export class Recorder { } record() { + this.setParent(this.node) this.setScopeMap(this.node, this.scope); this.recordInfo(this.node, this.scope); return this.node; @@ -80,13 +82,21 @@ export class Recorder { return this.ClassGroupOfNoCtor; } - private recordInfo(node: ts.Node, scope: Scope) { + private setParent(node: ts.Node) { node.forEachChild(childNode => { if (childNode!.parent == undefined || childNode.parent.kind != node.kind) { childNode = jshelpers.setParent(childNode, node)!; // childNode = ts.setTextRange(childNode, node)!; } - checkSyntaxError(childNode); + this.setParent(childNode); + }); + } + + private recordInfo(node: ts.Node, scope: Scope) { + node.forEachChild(childNode => { + if (isBeforeCompile()) { + checkSyntaxError(childNode); + } switch (childNode.kind) { case ts.SyntaxKind.FunctionExpression: case ts.SyntaxKind.MethodDeclaration: @@ -205,7 +215,7 @@ export class Recorder { let parent = this.getDeclarationNodeOfId(id); if (parent) { - console.log(id.getText()); + // console.log(id.getText()); let declKind = astutils.getVarDeclarationKind(parent); // collect declaration information to corresponding scope diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 61e13ea2ac..0c52f07611 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -135,9 +135,9 @@ export class Ts2Panda { static dumpConstantPool(ts2abc: any): void { let literalArrays = PandaGen.getLiteralArrayBuffer(); - console.log("-=-=-=-length=-=-=-=-=-="); + // console.log("-=-=-=-length=-=-=-=-=-="); for (let e of PandaGen.getLiteralArrayBuffer()) { - console.log(JSON.parse(JSON.stringify(e))); + // console.log(JSON.parse(JSON.stringify(e))); } if (CmdOptions.isEnableDebugLog()) { @@ -178,14 +178,14 @@ export class Ts2Panda { let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); let typeRecord = pg.getLocals(); - console.log("\\\\\\-= funcNmae =-\\\\\\ - ", funcName); + // console.log("\\\\\\-= funcNmae =-\\\\\\ - ", funcName); let typeInfo = new Array(); typeRecord.forEach((vreg) => { let typeOfVreg = new TypeOfVreg(vreg.num, vreg.getTypeIndex()); typeInfo.push(typeOfVreg); - console.log("\\\\\\\\\\\\ vreg num \\\\\\\\\\", vreg.num); - console.log("\\\\\\\\\\\\ vreg type \\\\\\\\\\", vreg.getTypeIndex()); + // console.log("\\\\\\\\\\\\ vreg num \\\\\\\\\\", vreg.num); + // console.log("\\\\\\\\\\\\ vreg type \\\\\\\\\\", vreg.getTypeIndex()); }); let variables, sourceCode; diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index 62014444ab..af43623e51 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -37,7 +37,7 @@ export class TypeChecker { let testClassType = new ClassType(targetNode, nameNode); } } - // console.log(type.getSymbol()?.valueDeclaration); + // // console.log(type.getSymbol()?.valueDeclaration); }) } } diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index dc91778d6d..73864132b3 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -49,8 +49,8 @@ export abstract class Variable { bindVreg(vreg: VReg) { this.vreg = vreg; this.vreg.setTypeIndex(this.typeIndex); - console.log("==== bindVreg var Name ====: ", this.name); - console.log("==== bindVreg typeIndex ====: ", this.typeIndex); + // console.log("==== bindVreg var Name ====: ", this.name); + // console.log("==== bindVreg typeIndex ====: ", this.typeIndex); } hasAlreadyBinded(): boolean { -- Gitee From c0074c4fb293cdd753799da6865026492e7b52d7 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Wed, 13 Oct 2021 12:02:09 +0800 Subject: [PATCH 34/39] ignore import error information Signed-off-by: zhangrengao Change-Id: Id7246438beb874d435a8312887a7fe720d80ea6a --- ts2panda/src/compiler.ts | 2 +- ts2panda/src/index.ts | 4 +--- ts2panda/src/modules.ts | 2 +- ts2panda/src/variable.ts | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index 2b2e39a916..a79f7d0eb2 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -1418,7 +1418,7 @@ export class Compiler { loadTarget(node: ts.Node, variable: { scope: Scope | undefined, level: number, v: Variable | undefined }) { if (variable.v instanceof ModuleVariable) { - this.pandaGen.loadModuleVariable(node, variable.v.getModule(), variable.v.getExoticName()); + // this.pandaGen.loadModuleVariable(node, variable.v.getModule(), variable.v.getExoticName()); } else if (variable.v instanceof LocalVariable) { if (variable.v.isLetOrConst() || variable.v.isClass()) { if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 1609a488dd..e262ace20f 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -61,7 +61,6 @@ function main(fileNames: string[], options: ts.CompilerOptions) { let newNode = ts.createSourceFile(node.fileName, text, options.target!); node = newNode; } - // console.log("----------------------------------- after --------------------------------"); let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); @@ -109,7 +108,7 @@ namespace Compiler { noEmitOnError: true, noImplicitAny: true, target: ts.ScriptTarget.ES2015, - module: ts.ModuleKind.CommonJS, + module: ts.ModuleKind.ES2015, strictNullChecks: true, skipLibCheck: true, alwaysStrict: true @@ -134,7 +133,6 @@ function run(args: string[], options?: ts.CompilerOptions): void { if (err instanceof diag.DiagnosticError) { let diagnostic = diag.getDiagnostic(err.code); - console.log(diagnostic) if (diagnostic != undefined) { let diagnosticLog = diag.createDiagnostic(err.file, err.irnode, diagnostic, ...err.args); diag.printDiagnostic(diagnosticLog); diff --git a/ts2panda/src/modules.ts b/ts2panda/src/modules.ts index 705cba7b64..f75263aace 100644 --- a/ts2panda/src/modules.ts +++ b/ts2panda/src/modules.ts @@ -119,7 +119,7 @@ export function setExportBinding(exportStmts: Array, moduleScope: Mo } if (v instanceof ModuleVariable) { - pandagen.loadModuleVariable(exportStmt.getNode(), v.getModule(), v.getName()); + //pandagen.loadModuleVariable(exportStmt.getNode(), v.getModule(), v.getName()); pandagen.storeModuleVar(exportStmt.getNode(), key); } else { (v).setExport(); diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 73864132b3..08fe70414a 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -178,7 +178,7 @@ export class ModuleVariable extends LocalVariable { getModule() { if (!this.module) { - throw new Error("Variable's module has not been binded"); + // throw new Error("Variable's module has not been binded"); } return this.module; } -- Gitee From 2d89477ca6e0317ef5d99e2efd2b76c0126e6291 Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Wed, 13 Oct 2021 14:15:36 +0800 Subject: [PATCH 35/39] =?UTF-8?q?ets=E6=89=93hap=E5=8C=85=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgy-ian --- ts2panda/src/compiler.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index a79f7d0eb2..b7ffd78d79 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -812,6 +812,8 @@ export class Compiler { case ts.SyntaxKind.ClassExpression: compileClassDeclaration(this, expr); break; + case ts.SyntaxKind.PartiallyEmittedExpression: + break; default: throw new Error("Expression of type " + this.getNodeName(expr) + " is unimplemented"); } -- Gitee From 95b30f51901d088e349e8c85f148f1f1aaf3bd73 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 13 Oct 2021 14:18:40 +0800 Subject: [PATCH 36/39] Avoid recording typeInfo during before when recording for syntaxChecking Signed-off-by: zhuoli Change-Id: I667e15d3cbe76e3d839ea3bd08e3160f979571b7 --- ts2panda/src/base/typeSystem.ts | 8 ++++---- ts2panda/src/compilerDriver.ts | 10 +++++----- ts2panda/src/recorder.ts | 8 ++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index c2e15345c6..285bada29d 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -211,7 +211,6 @@ export class ClassType extends BaseType { constructor(classNode: ts.ClassDeclaration, newExpressionFlag: boolean, variableNode?: ts.Node) { super(); - let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type @@ -398,19 +397,20 @@ export class ClassInstType extends BaseType { constructor(variableNode: ts.Node, referredClassIndex: number) { super(); // use referedClassIndex to point to the actually class type of this instance + console.log("referredClassIndex", referredClassIndex); this.referredClassIndex = referredClassIndex; // map variable to classInstType, which has a newly generated index - let currIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + let currIndex = this.getIndexFromTypeArrayBuffer(this); this.setVariable2Type(variableNode, currIndex); - this.setTypeArrayBuffer(this, currIndex); } transfer2LiteralBuffer(): LiteralBuffer { let classInstBuf = new LiteralBuffer(); let classInstLiterals: Array = new Array(); + classInstLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.CLASSINST)); - classInstLiterals.push(new Literal(LiteralTag.INTEGER, this.referredClassIndex)); + classInstLiterals.push(new Literal(LiteralTag.INTEGER, this.referredClassIndex + PrimitiveType._LENGTH)); classInstBuf.addLiterals(...classInstLiterals); return classInstBuf; diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index eac76181cb..03bf79fcf2 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -144,7 +144,7 @@ export class CompilerDriver { } compileForSyntaxCheck(node: ts.SourceFile): void { - let recorder = this.compilePrologue(node); + let recorder = this.compilePrologue(node, false); checkDuplicateDeclaration(recorder); checkExportEntries(recorder); } @@ -161,7 +161,7 @@ export class CompilerDriver { }); } - let recorder = this.compilePrologue(node); + let recorder = this.compilePrologue(node, true); // initiate ts2abc if (!CmdOptions.isAssemblyMode()) { @@ -239,7 +239,7 @@ export class CompilerDriver { } compileUnitTest(node: ts.SourceFile): void { - let recorder = this.compilePrologue(node); + let recorder = this.compilePrologue(node, true); for (let i = 0; i < this.pendingCompilationUnits.length; i++) { let unit: PendingCompilationUnit = this.pendingCompilationUnits[i]; @@ -267,7 +267,7 @@ export class CompilerDriver { this.compilationUnits.push(pandaGen); } - private compilePrologue(node: ts.SourceFile) { + private compilePrologue(node: ts.SourceFile, recordType: boolean) { let topLevelScope: GlobalScope | ModuleScope; if (CmdOptions.isModules()) { topLevelScope = new ModuleScope(node); @@ -275,7 +275,7 @@ export class CompilerDriver { topLevelScope = new GlobalScope(node); } - let recorder = new Recorder(node, topLevelScope, this); + let recorder = new Recorder(node, topLevelScope, this, recordType); recorder.record(); addVariableToScope(recorder); diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 918a7a0c7d..6841e96630 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -54,6 +54,7 @@ export class Recorder { node: ts.Node; scope: Scope; compilerDriver: CompilerDriver; + recordType: boolean; private scopeMap: Map = new Map(); private hoistMap: Map = new Map(); private parametersMap: Map = new Map(); @@ -63,10 +64,11 @@ export class Recorder { private exportStmts: Array = []; private defaultUsed: boolean = false; - constructor(node: ts.Node, scope: Scope, compilerDriver: CompilerDriver) { + constructor(node: ts.Node, scope: Scope, compilerDriver: CompilerDriver, recordType: boolean) { this.node = node; this.scope = scope; this.compilerDriver = compilerDriver; + this.recordType = recordType; this.funcNameMap = new Map(); this.funcNameMap.set("main", 1); } @@ -177,7 +179,9 @@ export class Recorder { break; } case ts.SyntaxKind.VariableStatement: { - TypeChecker.getInstance().formatNodeType(childNode); + if (this.recordType) { + TypeChecker.getInstance().formatNodeType(childNode); + } this.recordInfo(childNode, scope); break; } -- Gitee From 7573f17ae2746be184f050bc2c6c08c85e52db68 Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Thu, 14 Oct 2021 09:19:07 +0800 Subject: [PATCH 37/39] =?UTF-8?q?=E6=89=93ets=E5=BA=94=E7=94=A8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=82=E9=85=8D=20Signed-off-by:=20zgy-ian=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ts2panda/src/base/typeSystem.ts | 2 +- ts2panda/src/base/util.ts | 9 ---- ts2panda/src/index.ts | 3 -- ts2panda/src/recorder.ts | 3 +- ts2panda/src/typeChecker.ts | 96 ++++++++++++++++----------------- 5 files changed, 50 insertions(+), 63 deletions(-) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 285bada29d..b89dd74d81 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -397,7 +397,7 @@ export class ClassInstType extends BaseType { constructor(variableNode: ts.Node, referredClassIndex: number) { super(); // use referedClassIndex to point to the actually class type of this instance - console.log("referredClassIndex", referredClassIndex); + // console.log("referredClassIndex", referredClassIndex); this.referredClassIndex = referredClassIndex; // map variable to classInstType, which has a newly generated index diff --git a/ts2panda/src/base/util.ts b/ts2panda/src/base/util.ts index 0d89ae3f55..3c141cb824 100755 --- a/ts2panda/src/base/util.ts +++ b/ts2panda/src/base/util.ts @@ -295,13 +295,4 @@ export function getRangeStartVregPos(ins: IRNode): number { return -1; } return ins instanceof EcmaCreateobjectwithexcludedkeys ? 2 : 1; -} - -let isBeforeCompileFlag : boolean = false; -export function isBeforeCompile():boolean { - return isBeforeCompileFlag; -} - -export function setBeforeCompileFlag(flag: boolean){ - isBeforeCompileFlag = flag; } \ No newline at end of file diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index e262ace20f..ce7c2c6997 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -26,7 +26,6 @@ import { setGlobalStrict } from "./strictMode"; import jshelpers = require("./jshelpers"); import { TypeChecker } from "./typeChecker"; import { TypeRecorder } from "./typeRecorder"; -import {setBeforeCompileFlag} from "./base/util"; function main(fileNames: string[], options: ts.CompilerOptions) { let program = ts.createProgram(fileNames, options); @@ -42,7 +41,6 @@ function main(fileNames: string[], options: ts.CompilerOptions) { before: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { - setBeforeCompileFlag(true); let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); compilerDriver.compileForSyntaxCheck(node); @@ -53,7 +51,6 @@ function main(fileNames: string[], options: ts.CompilerOptions) { after: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { - setBeforeCompileFlag(false); let nodeBak = node; if (ts.getEmitHelpers(node)) { const printer: ts.Printer = ts.createPrinter({newLine:ts.NewLineKind.LineFeed}); diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 6841e96630..41b8032d75 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -48,7 +48,6 @@ import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; import { TypeChecker } from "./typeChecker"; -import {isBeforeCompile} from "./base/util"; export class Recorder { node: ts.Node; @@ -96,7 +95,7 @@ export class Recorder { private recordInfo(node: ts.Node, scope: Scope) { node.forEachChild(childNode => { - if (isBeforeCompile()) { + if (!this.recordType) { checkSyntaxError(childNode); } switch (childNode.kind) { diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index d1166d036a..c820d12c60 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -1,48 +1,48 @@ -import ts from "typescript"; -import { ClassType } from "./base/typeSystem"; - -export class TypeChecker { - private static instance: TypeChecker; - private compiledTypeChecker: any = null; - private constructor() {} - - public static getInstance(): TypeChecker { - if (!TypeChecker.instance) { - TypeChecker.instance = new TypeChecker(); - } - return TypeChecker.instance; - } - - public setTypeChecker(typeChecker: ts.TypeChecker) { - this.compiledTypeChecker = typeChecker; - } - - public getTypeChecker() : ts.TypeChecker { - return this.compiledTypeChecker; - } - - public formatNodeType(node: ts.Node) { - if (this.compiledTypeChecker === null) { - return ; - } - if (node.kind === ts.SyntaxKind.VariableStatement) { - const variableStatementNode = node; - const decList = variableStatementNode.declarationList; - decList.declarations.forEach(declaration => { - const nameNode = declaration.name; - let newExpressionFlag = false; - if (declaration.initializer && declaration.initializer.kind == ts.SyntaxKind.NewExpression) { - newExpressionFlag = true; - } - let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); - let targetNode = type.getSymbol()?.valueDeclaration; - if (targetNode) { - if (ts.isClassDeclaration(targetNode!)) { - let testClassType = new ClassType(targetNode, newExpressionFlag, nameNode); - } - } - // // console.log(type.getSymbol()?.valueDeclaration); - }) - } - } -} +import ts from "typescript"; +import { ClassType } from "./base/typeSystem"; + +export class TypeChecker { + private static instance: TypeChecker; + private compiledTypeChecker: any = null; + private constructor() {} + + public static getInstance(): TypeChecker { + if (!TypeChecker.instance) { + TypeChecker.instance = new TypeChecker(); + } + return TypeChecker.instance; + } + + public setTypeChecker(typeChecker: ts.TypeChecker) { + this.compiledTypeChecker = typeChecker; + } + + public getTypeChecker() : ts.TypeChecker { + return this.compiledTypeChecker; + } + + public formatNodeType(node: ts.Node) { + if (this.compiledTypeChecker === null) { + return ; + } + if (node.kind === ts.SyntaxKind.VariableStatement) { + const variableStatementNode = node; + const decList = variableStatementNode.declarationList; + decList.declarations.forEach(declaration => { + const nameNode = declaration.name; + let newExpressionFlag = false; + if (declaration.initializer && declaration.initializer.kind == ts.SyntaxKind.NewExpression) { + newExpressionFlag = true; + } + let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); + let targetNode = type.getSymbol()?.valueDeclaration; + if (targetNode) { + if (ts.isClassDeclaration(targetNode!)) { + let testClassType = new ClassType(targetNode, newExpressionFlag, nameNode); + } + } + // console.log(type.getSymbol()?.valueDeclaration); + }) + } + } +} -- Gitee From c762ea7ac58677360b4bbdb46fb26baf4bcffba0 Mon Sep 17 00:00:00 2001 From: zgy-ian Date: Sat, 23 Oct 2021 17:57:03 +0800 Subject: [PATCH 38/39] =?UTF-8?q?=E8=A7=A3=E5=86=B3ets=E6=89=93=E5=8C=85?= =?UTF-8?q?=E2=80=9CCannot=20find=20module=E2=80=9D=20=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20Signed-off-by:=20zgy-ian=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ts2panda/src/cmdOptions.ts | 2 ++ ts2panda/src/index.ts | 17 +++++++++++------ ts2panda/src/typeChecker.ts | 10 +++++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 6a14324b7f..dbe0e8bde3 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -39,6 +39,8 @@ const ts2pandaOptions = [ { name: 'bc-min-version', type: Boolean, defaultValue: false, description: "Print ark bytecode minimum supported version"} ] + + export class CmdOptions { private static parsedResult: ts.ParsedCommandLine; private static options: commandLineArgs.CommandLineOptions; diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index ce7c2c6997..36cbf1d8c1 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -23,9 +23,10 @@ import { CacheExpander } from "./pass/cacheExpander"; import { ICPass } from "./pass/ICPass"; import { RegAlloc } from "./regAllocator"; import { setGlobalStrict } from "./strictMode"; -import jshelpers = require("./jshelpers"); import { TypeChecker } from "./typeChecker"; import { TypeRecorder } from "./typeRecorder"; +import jshelpers = require("./jshelpers"); +import path = require("path"); function main(fileNames: string[], options: ts.CompilerOptions) { let program = ts.createProgram(fileNames, options); @@ -51,9 +52,8 @@ function main(fileNames: string[], options: ts.CompilerOptions) { after: [ (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { - let nodeBak = node; if (ts.getEmitHelpers(node)) { - const printer: ts.Printer = ts.createPrinter({newLine:ts.NewLineKind.LineFeed}); + const printer: ts.Printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); const text: string = printer.printNode(ts.EmitHint.Unspecified, node, node); let newNode = ts.createSourceFile(node.fileName, text, options.target!); node = newNode; @@ -72,7 +72,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { } compilerDriver.compile(node); compilerDriver.showStatistics(); - return nodeBak; + return node; } } ] @@ -91,7 +91,13 @@ function main(fileNames: string[], options: ts.CompilerOptions) { function getOutputBinName(node: ts.SourceFile) { let outputBinName = CmdOptions.getOutputBinName(); let fileName = node.fileName.substring(0, node.fileName.lastIndexOf('.')); - if (fileName != CmdOptions.getInputFileName()) { + let inputFileName = CmdOptions.getInputFileName(); + if (/^win/.test(require('os').platform())) { + var inputFileTmps = inputFileName.split(path.sep); + inputFileName = path.posix.join(...inputFileTmps); + } + + if (fileName != inputFileName) { outputBinName = fileName + ".abc"; } return outputBinName; @@ -128,7 +134,6 @@ function run(args: string[], options?: ts.CompilerOptions): void { main(parsed.fileNames, parsed.options); } catch (err) { if (err instanceof diag.DiagnosticError) { - let diagnostic = diag.getDiagnostic(err.code); if (diagnostic != undefined) { let diagnosticLog = diag.createDiagnostic(err.file, err.irnode, diagnostic, ...err.args); diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index c820d12c60..4b3aa893c3 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -4,7 +4,7 @@ import { ClassType } from "./base/typeSystem"; export class TypeChecker { private static instance: TypeChecker; private compiledTypeChecker: any = null; - private constructor() {} + private constructor() { } public static getInstance(): TypeChecker { if (!TypeChecker.instance) { @@ -17,13 +17,13 @@ export class TypeChecker { this.compiledTypeChecker = typeChecker; } - public getTypeChecker() : ts.TypeChecker { + public getTypeChecker(): ts.TypeChecker { return this.compiledTypeChecker; } public formatNodeType(node: ts.Node) { if (this.compiledTypeChecker === null) { - return ; + return; } if (node.kind === ts.SyntaxKind.VariableStatement) { const variableStatementNode = node; @@ -34,8 +34,8 @@ export class TypeChecker { if (declaration.initializer && declaration.initializer.kind == ts.SyntaxKind.NewExpression) { newExpressionFlag = true; } - let type: ts.Type = this.compiledTypeChecker.getTypeAtLocation(nameNode); - let targetNode = type.getSymbol()?.valueDeclaration; + let symbol: ts.Symbol = this.compiledTypeChecker.getSymbolAtLocation(nameNode); + let targetNode = symbol?.valueDeclaration; if (targetNode) { if (ts.isClassDeclaration(targetNode!)) { let testClassType = new ClassType(targetNode, newExpressionFlag, nameNode); -- Gitee From 75727e52aca6366e74492f005e3965b59c829db5 Mon Sep 17 00:00:00 2001 From: hufeng Date: Mon, 25 Oct 2021 16:03:41 +0800 Subject: [PATCH 39/39] fix module's variable storing Signed-off-by: hufeng Change-Id: I1f0114bf2c1f5393936cfd99b8f45d12dbee5f3a --- ts2panda/src/addVariable2Scope.ts | 7 ------- ts2panda/src/compiler.ts | 26 ++++++++++++++------------ ts2panda/src/compilerDriver.ts | 4 ++-- ts2panda/src/lexenv.ts | 5 ++--- ts2panda/src/modules.ts | 31 ++++++++++++++----------------- ts2panda/src/recorder.ts | 5 ++--- ts2panda/src/scope.ts | 10 ---------- ts2panda/src/variable.ts | 31 ------------------------------- 8 files changed, 34 insertions(+), 85 deletions(-) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index e6a725d098..72ecf519bf 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -25,8 +25,6 @@ import { FuncDecl, InitStatus, LetDecl, - ModDecl, - ModuleScope, Scope, VarDecl, VariableScope @@ -146,11 +144,6 @@ export function addVariableToScope(recorder: Recorder) { } else if (decl instanceof CatchParameter) { v = scope.add(decl.name, VarDeclarationKind.LET); setVariableOrParameterType(decl.node, v); - } else if (decl instanceof ModDecl) { - if (!(scope instanceof ModuleScope)) { - throw new Error("ModuleVariable can't exist without ModuleScope"); - } - v = scope.add(decl.name, VarDeclarationKind.MODULE); } else if (decl instanceof ClassDecl) { let classNode = decl.node; if (ts.isClassDeclaration(classNode)) { diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index b7ffd78d79..b8b9f12af5 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -111,7 +111,6 @@ import { isAssignmentOperator } from "./syntaxCheckHelper"; import { GlobalVariable, LocalVariable, - ModuleVariable, VarDeclarationKind, Variable } from "./variable"; @@ -1368,16 +1367,18 @@ export class Compiler { isDeclaration: boolean) { if (variable.v instanceof LocalVariable) { if (isDeclaration) { - if (variable.v.isLet()) { + if (variable.v.isLetOrConst()) { variable.v.initialize(); if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { - this.pandaGen.stLetToGlobalRecord(node, variable.v.getName()); - return; - } - } else if (variable.v.isConst()) { - variable.v.initialize(); - if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { - this.pandaGen.stConstToGlobalRecord(node, variable.v.getName()); + if (variable.v.isLet()) { + this.pandaGen.stLetToGlobalRecord(node, variable.v.getName()); + } else { + this.pandaGen.stConstToGlobalRecord(node, variable.v.getName()); + } + + if (variable.v.isExportVar()) { + this.pandaGen.storeModuleVar(node, variable.v.getExportedName()); + } return; } } @@ -1386,6 +1387,9 @@ export class Compiler { if (variable.v.isLetOrConst()) { if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { this.pandaGen.tryStoreGlobalByName(node, variable.v.getName()); + if (variable.v.isExportVar()) { + this.pandaGen.storeModuleVar(node, variable.v.getExportedName()); + } return; } } @@ -1419,9 +1423,7 @@ export class Compiler { } loadTarget(node: ts.Node, variable: { scope: Scope | undefined, level: number, v: Variable | undefined }) { - if (variable.v instanceof ModuleVariable) { - // this.pandaGen.loadModuleVariable(node, variable.v.getModule(), variable.v.getExoticName()); - } else if (variable.v instanceof LocalVariable) { + if (variable.v instanceof LocalVariable) { if (variable.v.isLetOrConst() || variable.v.isClass()) { if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { this.pandaGen.tryLoadGlobalByName(node, variable.v.getName()); diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index 03bf79fcf2..823dccbcb5 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -212,7 +212,7 @@ export class CompilerDriver { let compiler = new Compiler(node, pandaGen, this, recorder); if (CmdOptions.isModules() && ts.isSourceFile(node) && scope instanceof ModuleScope) { - setImport(recorder.getImportStmts(), scope, pandaGen, compiler); + setImport(recorder.getImportStmts(), scope, pandaGen); setExportBinding(recorder.getExportStmts(), scope, pandaGen); } @@ -255,7 +255,7 @@ export class CompilerDriver { let compiler = new Compiler(node, pandaGen, this, recorder); if (CmdOptions.isModules() && ts.isSourceFile(node) && scope instanceof ModuleScope) { - setImport(recorder.getImportStmts(), scope, pandaGen, compiler); + setImport(recorder.getImportStmts(), scope, pandaGen); setExportBinding(recorder.getExportStmts(), scope, pandaGen); } diff --git a/ts2panda/src/lexenv.ts b/ts2panda/src/lexenv.ts index 3193042838..eec0a29046 100644 --- a/ts2panda/src/lexenv.ts +++ b/ts2panda/src/lexenv.ts @@ -35,7 +35,6 @@ import { PandaGen } from "./pandagen"; import { Scope } from "./scope"; import { LocalVariable, - ModuleVariable, Variable } from "./variable"; import jshelpers from "./jshelpers"; @@ -161,7 +160,7 @@ export class VariableAcessStore extends VariableAccessBase { insns.push(storeAccumulator(bindVreg)); - if (v.isExportVar() && !(v instanceof ModuleVariable)) { + if (v.isExportVar()) { insns.push(storeModuleVariable(v.getExportedName())); } @@ -197,7 +196,7 @@ export class VariableAcessStore extends VariableAccessBase { insns.push(storeLexicalVar(this.level, slot, valueReg)); insns.push(loadAccumulator(valueReg)); - if (v.isExportVar() && !(v instanceof ModuleVariable)) { + if (v.isExportVar()) { insns.push(storeModuleVariable(v.getExportedName())); } pandaGen.freeTemps(valueReg); diff --git a/ts2panda/src/modules.ts b/ts2panda/src/modules.ts index f75263aace..ef8c49b641 100644 --- a/ts2panda/src/modules.ts +++ b/ts2panda/src/modules.ts @@ -16,10 +16,9 @@ import * as ts from "typescript"; import { PandaGen } from "./pandagen"; import jshelpers from "./jshelpers"; -import { LocalVariable, ModuleVariable } from "./variable"; +import { LocalVariable } from "./variable"; import { DiagnosticCode, DiagnosticError } from "./diagnostic"; import { ModuleScope } from "./scope"; -import { Compiler } from "./compiler"; export class ModuleStmt { private node: ts.Node @@ -69,23 +68,26 @@ export class ModuleStmt { } } -export function setImport(importStmts: Array, moduleScope: ModuleScope, pandagen: PandaGen, compiler: Compiler) { +export function setImport(importStmts: Array, moduleScope: ModuleScope, pandagen: PandaGen) { importStmts.forEach((importStmt) => { pandagen.importModule(importStmt.getNode(), importStmt.getModuleRequest()); - let moduleReg = pandagen.allocLocalVreg(); - pandagen.storeAccumulator(importStmt.getNode(), moduleReg); - + // import * as xxx from "a.js" if (importStmt.getNameSpace()) { let v = moduleScope.findLocal(importStmt.getNameSpace())!; - pandagen.storeAccToLexEnv(importStmt.getNode(), moduleScope, 0, v, true); + pandagen.stConstToGlobalRecord(importStmt.getNode(), v.getName()); (v).initialize(); } + // import { ... } from "a.js" + // import defaultExport, * as a from "a.js" + let moduleReg = pandagen.allocLocalVreg(); + pandagen.storeAccumulator(importStmt.getNode(), moduleReg); + let bindingNameMap = importStmt.getBindingNameMap(); bindingNameMap.forEach((value: string, key: string) => { - let v = moduleScope.findLocal(key)!; - v.bindModuleVreg(moduleReg); - v.setExoticName(value); + let v = moduleScope.findLocal(key)!; + pandagen.loadObjProperty(importStmt.getNode(), moduleReg, value); + pandagen.stConstToGlobalRecord(importStmt.getNode(), v.getName()); }); }) } @@ -118,13 +120,8 @@ export function setExportBinding(exportStmts: Array, moduleScope: Mo throw new DiagnosticError(exportStmt.getNode(), DiagnosticCode.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, jshelpers.getSourceFileOfNode(exportStmt.getNode()), [value]); } - if (v instanceof ModuleVariable) { - //pandagen.loadModuleVariable(exportStmt.getNode(), v.getModule(), v.getName()); - pandagen.storeModuleVar(exportStmt.getNode(), key); - } else { - (v).setExport(); - (v).setExportedName(key); - } + (v).setExport(); + (v).setExportedName(key); }); } }) diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 41b8032d75..22e73779ec 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -35,7 +35,6 @@ import { LetDecl, LocalScope, LoopScope, - ModDecl, ModuleScope, Scope, VarDecl, @@ -314,7 +313,7 @@ export class Recorder { // import defaultExport from "a.js" if (importClause.name) { let name = jshelpers.getTextOfIdentifierOrLiteral(importClause.name); - scope.setDecls(new ModDecl(name, importClause.name)); + scope.setDecls(new ConstDecl(name, importClause.name)); importStmt.addLocalName(name, "default"); } @@ -335,7 +334,7 @@ export class Recorder { namedBindings.elements.forEach((element) => { let name: string = jshelpers.getTextOfIdentifierOrLiteral(element.name); let exoticName: string = element.propertyName ? jshelpers.getTextOfIdentifierOrLiteral(element.propertyName) : name; - scope.setDecls(new ModDecl(name, element)); + scope.setDecls(new ConstDecl(name, element)); importStmt.addLocalName(name, exoticName); }); } diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index e2aa29a062..3885a0da56 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -19,7 +19,6 @@ import { LOGD, LOGE } from "./log"; import { GlobalVariable, LocalVariable, - ModuleVariable, VarDeclarationKind, Variable } from "./variable"; @@ -55,12 +54,6 @@ export class ConstDecl extends Decl { } } -export class ModDecl extends Decl { - constructor(localName: string, node: ts.Node) { - super(localName, node); - } -} - export class FuncDecl extends Decl { readonly index: number; constructor(funcName: string, node: ts.Node, index: number) { @@ -393,9 +386,6 @@ export class ModuleScope extends VariableScope { } else if (declKind == VarDeclarationKind.VAR || declKind == VarDeclarationKind.FUNCTION) { v = new LocalVariable(declKind, name); this.locals.push(v); - } else if (declKind == VarDeclarationKind.MODULE) { - v = new ModuleVariable(VarDeclarationKind.CONST, name, InitStatus.INITIALIZED); - this.locals.push(v); } else { v = new LocalVariable(declKind, name, status); this.locals.push(v); diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 08fe70414a..e43625b15b 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -153,37 +153,6 @@ export class LocalVariable extends Variable { } } -export class ModuleVariable extends LocalVariable { - private module: VReg | undefined; - private exoticName: string = ""; - - constructor(declKind: VarDeclarationKind, name: string, status: InitStatus) { - super(declKind, name, status); - } - - bindModuleVreg(vreg: VReg) { - this.module = vreg; - } - - setExoticName(exoticName: string) { - this.exoticName = exoticName; - } - - getExoticName() { - if (this.exoticName == "") { - throw new Error("Variable doesn't have exotic name"); - } - return this.exoticName; - } - - getModule() { - if (!this.module) { - // throw new Error("Variable's module has not been binded"); - } - return this.module; - } -} - export class GlobalVariable extends Variable { constructor(declKind: VarDeclarationKind, name: string) { super(declKind, name); -- Gitee