diff --git a/test262/config.py b/test262/config.py index c521b973dd530584ae87c384f91dde836def4731..20e874022987e9c14e5d4c3b15055d7ebeb0f9ce 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 97752ef074164566fb3186cad224d9c84d6cc53e..7f9bce461f465f4b0e9774aae94e6b0be02f3254 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 212e144a548b4ae7a797b8351eb932668596d26a..86596f8c94d73d534f379b28a73f41067dc5dc7b 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 = "" } @@ -314,3 +322,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/package-lock.json b/ts2panda/package-lock.json old mode 100644 new mode 100755 index e18acb061b27108ec6cbaa58cb9e2cb1e6dc877d..646821ba8881cb3f9add02ae06249b613d902356 --- a/ts2panda/package-lock.json +++ b/ts2panda/package-lock.json @@ -2319,9 +2319,9 @@ "dev": true }, "typescript": { - "version": "3.9.10", - "resolved": "https://repo.huaweicloud.com/repository/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 2fc7bed3c1bea20b335152cec5b95574d1ef154e..f37f0d41b643c30529a895a3837a4db118232e35 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/scripts/npm-install.sh b/ts2panda/scripts/npm-install.sh new file mode 100755 index 0000000000000000000000000000000000000000..f806d55df01d96557ff8b668c4090dc52b11d790 --- /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/scripts/run_tests.py b/ts2panda/scripts/run_tests.py new file mode 100755 index 0000000000000000000000000000000000000000..616f14f1e0b1ab932ecfe3b5258021087e6a5861 --- /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/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 8ecc7a1d3fcf59e2b3bad1383a79e4c53e8a7dd8..72ecf519bf8faebc288e38caba6bcf1ab2801219 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -25,15 +25,39 @@ import { FuncDecl, InitStatus, LetDecl, - ModDecl, - ModuleScope, Scope, VarDecl, VariableScope } from "./scope"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; -import { VarDeclarationKind } from "./variable"; +import { + VarDeclarationKind, + 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); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); + } + // // 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(ts.getOriginalNode(node)); + if (typeIndex != -1) { + v.setTypeIndex(typeIndex + PrimitiveType._LENGTH); + } + // console.log("--node--", jshelpers.getTextOfNode(ts.getOriginalNode(node))); + // console.log("--node.type--", v.getTypeIndex()); + } +} function addInnerArgs(node: ts.Node, scope: VariableScope): void { // the first argument for js function is func_obj @@ -80,10 +104,15 @@ export function addVariableToScope(recorder: Recorder) { hoistDecls = hoistMap.get(scope); if (hoistDecls) { 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); + setVariableOrParameterType(hoistDecl.node, v); } else if (hoistDecl instanceof FuncDecl) { - scope.add(hoistDecl.name, VarDeclarationKind.FUNCTION); + v = scope.add(hoistDecl.name, VarDeclarationKind.FUNCTION); + setClassOrFunctionType(hoistDecl.node, v); } else { throw new Error("Wrong type of declaration to be hoisted") } @@ -100,27 +129,30 @@ export function addVariableToScope(recorder: Recorder) { if (hoistDecls && hoistDecls.includes(decl)) { continue; } - + // 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); + setVariableOrParameterType(decl.node, v); } else if (decl instanceof ConstDecl) { - scope.add(decl.name, VarDeclarationKind.CONST, InitStatus.UNINITIALIZED); + v = scope.add(decl.name, VarDeclarationKind.CONST, InitStatus.UNINITIALIZED); + setVariableOrParameterType(decl.node, v); } else if (decl instanceof FuncDecl) { - scope.add(decl.name, VarDeclarationKind.FUNCTION); + v = scope.add(decl.name, VarDeclarationKind.FUNCTION); + setClassOrFunctionType(decl.node, v); } else if (decl instanceof CatchParameter) { - 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.LET); + setVariableOrParameterType(decl.node, v); } 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); + setClassOrFunctionType(decl.node, v); } else { let classScope = recorder.getScopeOfNode(classNode); - classScope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + v = classScope.add(decl.name, VarDeclarationKind.CLASS, InitStatus.UNINITIALIZED); + setClassOrFunctionType(decl.node, v); } } else { /** @@ -130,7 +162,7 @@ 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); } } } @@ -138,6 +170,8 @@ export function addVariableToScope(recorder: Recorder) { } function addParameters(node: ts.FunctionLikeDeclaration, scope: VariableScope): void { + // 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]; @@ -148,8 +182,11 @@ 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); + let v = scope.addParameter(name, VarDeclarationKind.VAR, i + 1); + setVariableOrParameterType(param, v); } for (let i = 0; i < patternParams.length; i++) { diff --git a/ts2panda/src/assemblyDumper.ts b/ts2panda/src/assemblyDumper.ts index c425d876fd61d73eab8fac56a20e11827d81adf6..17892d53162edfd7137e0e0994ab3b201294a557 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/literal.ts b/ts2panda/src/base/literal.ts old mode 100755 new mode 100644 diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts new file mode 100644 index 0000000000000000000000000000000000000000..b89dd74d814b8cdfb6462b994bd9f315c7159234 --- /dev/null +++ b/ts2panda/src/base/typeSystem.ts @@ -0,0 +1,537 @@ +/* + * 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"; +import { + Literal, + LiteralBuffer, + LiteralTag +} from "./literal"; +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, + NUMBER, + BOOLEAN, + STRING, + SYMBOL, + VOID, + NULL, + UNDEFINED, + _LENGTH = 50 +} + +export enum L2Type { + CLASS, + CLASSINST, + FUNCTION, + 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 { + + 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; + 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; + if (identifierSymbol && identifierSymbol.declarations) { + return identifierSymbol!.declarations[0]; + } + return node; + } + + 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) { + this.typeRecorder.addType2Index(node, index); + } + + protected setVariable2Type(variableNode: ts.Node, index: number) { + this.typeRecorder.setVariable2Type(variableNode, index); + } + + protected createType(node: ts.Node, newExpressionFlag: boolean, 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, variableNode); + break; + } + case ts.SyntaxKind.ClassDeclaration: { + 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, 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, newExpressionFlag, variableNode); + typeIndex = this.typeRecorder.tryGetTypeIndex(typeNode); + } + return typeIndex; + } + + 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); + let typeIndex = -1; + if (typeFlagName in PrimitiveType) { + typeIndex = PrimitiveType[typeFlagName as keyof typeof PrimitiveType]; + } else { + let identifier = typeRef.getChildAt(0); + typeIndex = this.getOrCreateUserDefinedType(identifier, newExpressionFlag, variableNode); + } + // 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)); + } + return typeIndex!; + } + // console.log("WARNING: node type not found for: " + jshelpers.getTextOfNode(node)); + return -1; + } + + protected getIndexFromTypeArrayBuffer(type: BaseType): number { + return PandaGen.appendTypeArrayBuffer(type); + } + + protected setTypeArrayBuffer(type: BaseType, index: number) { + PandaGen.setTypeArrayBuffer(type, index); + } + + // temp for test + + 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: "); + // console.log(this.printMap(this.typeRecorder.getType2Index())); + // console.log("variable2Type: "); + // console.log(this.printMap(this.typeRecorder.getVariable2Type())); + // console.log("=============================="); + } +} + +export class PlaceHolderType extends BaseType { + transfer2LiteralBuffer(): LiteralBuffer { + return new LiteralBuffer(); + } +} + +export class ClassType extends BaseType { + modifier: number = 0; // 0 -> unabstract, 1 -> abstract; + heritages: Array = new Array(); + // 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(); + + 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 + this.addCurrentType(classNode, currIndex); + + this.fillInModifiers(classNode); + this.fillInHeritages(classNode); + this.fillInFieldsAndMethods(classNode); + + // initialization finished, add variable to type if variable is given + if (variableNode) { + // 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 + this.getLog(classNode, currIndex); + } + + private fillInModifiers(node: ts.ClassDeclaration) { + if (node.modifiers) { + for (let modifier of node.modifiers) { + switch (modifier.kind) { + case ts.SyntaxKind.AbstractKeyword: { + this.modifier = ModifierAbstract.ABSTRACT; + break; + } + case ts.SyntaxKind.ExportKeyword: { + break; + } + } + } + } + } + + 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, false); + this.heritages.push(heritageTypePos); + } + } + } + + private fillInFields(member: ts.PropertyDeclaration) { + // collect modifier info + 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"); + } + + // 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) { + switch (modifier.kind) { + case ts.SyntaxKind.StaticKeyword: { + isStatic = true; + break; + } + case ts.SyntaxKind.PrivateKeyword: { + fieldInfo[1] = AccessFlag.PRIVATE; + break; + } + case ts.SyntaxKind.ProtectedKeyword: { + fieldInfo[1] = AccessFlag.PROTECTED; + break; + } + case ts.SyntaxKind.ReadonlyKeyword: { + fieldInfo[2] = ModifierReadonly.READONLY; + break; + } + } + } + } + // collect type info + let variableNode = member.name ? member.name : undefined; + fieldInfo[0] = this.getTypeIndexForDeclWithType(member, variableNode); + + if (isStatic) { + this.staticFields.set(fieldName, fieldInfo); + } else { + this.fields.set(fieldName, fieldInfo); + } + } + + private fillInMethods(member: ClassMemberFunction) { + /** + * a method like declaration in a new class must be a new type, + * create this type and add it into typeRecorder + */ + let variableNode = member.name ? member.name : undefined; + let funcType = new FunctionType(member, variableNode); + + // Then, get the typeIndex and fill in the methods array + let typeIndex = this.typeRecorder.tryGetTypeIndex(member); + 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) { + switch (member.kind) { + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.Constructor: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: { + this.fillInMethods(member); + break; + } + case ts.SyntaxKind.PropertyDeclaration: { + this.fillInFields(member); + break; + } + } + } + } + } + + transfer2LiteralBuffer() { + let classTypeBuf = new LiteralBuffer(); + let classTypeLiterals: Array = new Array(); + // 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)); + this.heritages.forEach(heritage => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, heritage)); + }); + + // 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)); + this.methods.forEach(method => { + classTypeLiterals.push(new Literal(LiteralTag.INTEGER, method)); + }); + + classTypeBuf.addLiterals(...classTypeLiterals); + 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 ClassInstType extends BaseType { + referredClassIndex: number = 0; // the referred class in the type system; + 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(this); + this.setVariable2Type(variableNode, 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 + PrimitiveType._LENGTH)); + classInstBuf.addLiterals(...classInstLiterals); + + return classInstBuf; + } +} + +export class FunctionType extends BaseType { + name: string | undefined = ''; + accessFlag: number = 0; // 0 -> public -> 0, private -> 1, protected -> 2 + modifierStatic: number = 0; // 0 -> unstatic, 1 -> static + parameters: Array = new Array(); + returnType: number = 0; + + constructor(funcNode: ts.FunctionLikeDeclaration, 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 + this.addCurrentType(funcNode, currIndex); + + if (funcNode.name) { + this.name = jshelpers.getTextOfIdentifierOrLiteral(funcNode.name); + } else { + this.name = "constructor"; + } + this.fillInModifiers(funcNode); + this.fillInParameters(funcNode); + this.fillInReturn(funcNode); + + // initialization finished, add variable to type if variable is given + if (variableNode) { + this.setVariable2Type(variableNode, currIndex); + } + this.setTypeArrayBuffer(this, currIndex); + + // check typeRecorder + this.getLog(funcNode, currIndex); + } + + private fillInModifiers(node: ts.FunctionLikeDeclaration) { + if (node.modifiers) { + for (let modifier of node.modifiers) { + switch (modifier.kind) { + case ts.SyntaxKind.PrivateKeyword: { + this.accessFlag = AccessFlag.PRIVATE; + break; + } + case ts.SyntaxKind.ProtectedKeyword: { + this.accessFlag = AccessFlag.PROTECTED; + break; + } + case ts.SyntaxKind.StaticKeyword: { + this.modifierStatic = ModifierStatic.STATIC; + } + } + } + } + } + + private fillInParameters(node: ts.FunctionLikeDeclaration) { + if (node.parameters) { + for (let parameter of node.parameters) { + let variableNode = parameter; + let typeIndex = this.getTypeIndexForDeclWithType(parameter, variableNode); + this.parameters.push(typeIndex); + } + } + } + + private fillInReturn(node: ts.FunctionLikeDeclaration) { + let typeIndex = this.getTypeIndexForDeclWithType(node); + if (typeIndex != -1) { + this.returnType = typeIndex; + } + } + + getModifier() { + return this.modifierStatic; + } + + 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.STRING, this.name)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); + this.parameters.forEach((type) => { + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); + }); + + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); + 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 { + private vregNum: number; + private typeIndex: number; + + constructor(vregNum: number, typeIndex: number) { + this.vregNum = vregNum; + this.typeIndex = typeIndex; + } +} diff --git a/ts2panda/src/base/util.ts b/ts2panda/src/base/util.ts index c9a2177cadbb3a7a5f9ef364c1abc81d3f0cbc01..3c141cb82403db7c6b019471f02fdc7356eba619 100755 --- a/ts2panda/src/base/util.ts +++ b/ts2panda/src/base/util.ts @@ -295,4 +295,4 @@ export function getRangeStartVregPos(ins: IRNode): number { return -1; } return ins instanceof EcmaCreateobjectwithexcludedkeys ? 2 : 1; -} +} \ No newline at end of file diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 6a14324b7f9888be4733769f9c83c00aa53d944f..dbe0e8bde33abc7ad7356fc713b8edb55086773c 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/compiler.ts b/ts2panda/src/compiler.ts index b87ad4cc6a300f0aacccc882a40714e3d05e25dd..b8b9f12af55ae6f4e456e581a189890d604559a9 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"; @@ -109,7 +111,6 @@ import { isAssignmentOperator } from "./syntaxCheckHelper"; import { GlobalVariable, LocalVariable, - ModuleVariable, VarDeclarationKind, Variable } from "./variable"; @@ -336,6 +337,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 +563,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 +625,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); @@ -802,6 +811,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"); } @@ -1356,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; } } @@ -1374,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; } } @@ -1407,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 e8fa59c59695974570ff6e896c80f7103e2c54b5..823dccbcb51674848312ee173ca8127b2d9f2715 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -143,6 +143,12 @@ export class CompilerDriver { return spArray.reverse(); } + compileForSyntaxCheck(node: ts.SourceFile): void { + let recorder = this.compilePrologue(node, false); + checkDuplicateDeclaration(recorder); + checkExportEntries(recorder); + } + compile(node: ts.SourceFile): void { if (CmdOptions.showASTStatistics()) { let statics: number[] = new Array(ts.SyntaxKind.Count).fill(0); @@ -155,7 +161,7 @@ export class CompilerDriver { }); } - let recorder = this.compilePrologue(node); + let recorder = this.compilePrologue(node, true); // initiate ts2abc if (!CmdOptions.isAssemblyMode()) { @@ -206,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); } @@ -233,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]; @@ -249,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); } @@ -261,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); @@ -269,11 +275,9 @@ export class CompilerDriver { topLevelScope = new GlobalScope(node); } - let recorder = new Recorder(node, topLevelScope, this); + let recorder = new Recorder(node, topLevelScope, this, recordType); recorder.record(); - - checkDuplicateDeclaration(recorder); - checkExportEntries(recorder); + addVariableToScope(recorder); let postOrderVariableScopes = this.postOrderAnalysis(topLevelScope); diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index 527b8f0d50b933fcff00b9dff70631f05455dbf1..688eac267eeab3910fac3bb1d4784b2387f64719 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -171,8 +171,28 @@ export class DebugInfo { let firstStmt = pandaGen.getFirstStmt(); if (firstStmt) { let file = jshelpers.getSourceFileOfNode(firstStmt); - let loc = file.getLineAndCharacterOfPosition(firstStmt.getStart()); - let wholeLineText = firstStmt.getText(); + if (!file) { + return; + } + + 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); @@ -199,12 +219,29 @@ 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; } - 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; } @@ -381,4 +418,4 @@ export class DebugInfo { scope.setScopeEndIns(placeHolder); } } -} \ No newline at end of file +} diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index f778f0a75e74d54f8c02c1aacde5dfda9e89ed7e..36cbf1d8c1c5fff2e5f20b3620b9dbd241e1196f 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -23,10 +23,16 @@ import { CacheExpander } from "./pass/cacheExpander"; import { ICPass } from "./pass/ICPass"; import { RegAlloc } from "./regAllocator"; import { setGlobalStrict } from "./strictMode"; +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); + let typeChecker = TypeChecker.getInstance(); + TypeRecorder.createInstance(); + typeChecker.setTypeChecker(program.getTypeChecker()); let emitResult = program.emit( undefined, undefined, @@ -36,11 +42,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 +88,21 @@ 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('.')); + 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; +} + namespace Compiler { export namespace Options { export let Default: ts.CompilerOptions = { @@ -78,7 +111,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 diff --git a/ts2panda/src/jshelpers.d.ts b/ts2panda/src/jshelpers.d.ts index 5e4203d763b9c1b65c72a2f0fd558f8a7bad91da..7138633f30c10086bc2a3b57ff16ae3391172ba3 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 a958271e22bad6749ab86f42f2d5b206e8e343c9..e3c2960d8d8a8f3201a57ba2e2f9638f0cf0dacc 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/lexenv.ts b/ts2panda/src/lexenv.ts index 3193042838a25f81ce0067cc1dbe716719d86ac2..eec0a290460ee1aae43f98b87d60f4f76f3685ff 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 705cba7b642e6009c39a8908af94fc0a0a296769..ef8c49b641126c0c602970c2ad424014ef7f7a1a 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/pandagen.ts b/ts2panda/src/pandagen.ts index e823a721742aab76baff208acd0fb57a56475554..76355805f712ffcae164b79a6007181f1817fc05 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"; @@ -202,7 +203,7 @@ export class PandaGen { private sourceCodeDebugInfo: string | undefined; private icSize: number = 0; - private static literalArrayBuffer: Array = []; + private static literalArrayBuffer: Array = new Array(); constructor(internalName: string, parametersCount: number, scope: Scope | undefined = undefined) { this.internalName = internalName; @@ -257,6 +258,16 @@ export class PandaGen { this.icSize = total; } + static appendTypeArrayBuffer(type: BaseType): number { + let index = PandaGen.literalArrayBuffer.length; + 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/pandasm.ts b/ts2panda/src/pandasm.ts index f4ca2651ae12ef281ecff503794687a19fa6ae0f..154d51ad5d2d30afc57c23ad9eec219f8c8a95eb 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,6 +73,7 @@ export class Function { public variables: Array | undefined; public sourceFile: string; public sourceCode: string | undefined; + public typeInfo: Array; constructor( name: string, @@ -82,6 +84,7 @@ export class Function { variables: Array | undefined = undefined, sourceFile: string = "", sourceCode: string | undefined = undefined, + typeInfo: Array ) { this.name = name; this.signature = signature; @@ -93,6 +96,7 @@ export class Function { this.variables = variables; this.sourceFile = sourceFile; this.sourceCode = sourceCode; + this.typeInfo = typeInfo; } } diff --git a/ts2panda/src/patch.diff b/ts2panda/src/patch.diff new file mode 100644 index 0000000000000000000000000000000000000000..5c308190ca6b9ef05154cc6b960efd7ed38f5fa1 --- /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/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c3378feb0bff1e318a1e1610b83215a..22e73779ec51d14047c50f58c311a211dfb97737 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -35,25 +35,24 @@ import { LetDecl, LocalScope, LoopScope, - ModDecl, ModuleScope, Scope, VarDecl, VariableScope } from "./scope"; import { - AddCtor2Class, - isContainConstruct, - getClassNameForConstructor + AddCtor2Class, getClassNameForConstructor, isContainConstruct } from "./statement/classStatement"; import { checkSyntaxError } from "./syntaxChecker"; import { isGlobalIdentifier } from "./syntaxCheckHelper"; import { VarDeclarationKind } from "./variable"; +import { TypeChecker } from "./typeChecker"; 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,15 +62,17 @@ 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); } record() { + this.setParent(this.node) this.setScopeMap(this.node, this.scope); this.recordInfo(this.node, this.scope); return this.node; @@ -81,9 +82,21 @@ export class Recorder { return this.ClassGroupOfNoCtor; } + 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)!; + } + this.setParent(childNode); + }); + } + private recordInfo(node: ts.Node, scope: Scope) { node.forEachChild(childNode => { - checkSyntaxError(childNode); + if (!this.recordType) { + checkSyntaxError(childNode); + } switch (childNode.kind) { case ts.SyntaxKind.FunctionExpression: case ts.SyntaxKind.MethodDeclaration: @@ -163,6 +176,13 @@ export class Recorder { this.recordInfo(childNode, scope); break; } + case ts.SyntaxKind.VariableStatement: { + if (this.recordType) { + TypeChecker.getInstance().formatNodeType(childNode); + } + this.recordInfo(childNode, scope); + break; + } default: this.recordInfo(childNode, scope); } @@ -197,6 +217,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 @@ -217,7 +238,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 +257,7 @@ export class Recorder { if (name == "arguments") { let varialbeScope = scope.getNearestVariableScope(); - varialbeScope ?.setUseArgs(true); + varialbeScope?.setUseArgs(true); } } @@ -292,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"); } @@ -313,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); }); } @@ -493,8 +514,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/scope.ts b/ts2panda/src/scope.ts index e2aa29a06262b379970d0abd4e2ca518590cdc75..3885a0da561db32c1d368be2d19f3034afc80054 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/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 1163c9e0b86aadac244721c152ca0e0f6375d031..2478c7abffc22d95a98ade1dbaa2d10939d5d139 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,26 @@ 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 (!nearestFuncScope) { + return; + } 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 +424,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 +646,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 221db0bb2ea960d4c493bc41513e150f2f13867e..90510ba9b302d69ed5beac92d4b79c98e2a3bfe0 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 6107c014533de7d417e574d15db0263670f81620..d720e5420da8226cb338697f6cb146f30bf40d77 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,16 @@ 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); 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 +358,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/syntaxCheckHelper.ts b/ts2panda/src/syntaxCheckHelper.ts index 2c719c38f4175b8691a4eb8a4f3f505d39aea41d..8439b27263c0053e12b7543c7300efa8f5c99d11 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; diff --git a/ts2panda/src/syntaxChecker.ts b/ts2panda/src/syntaxChecker.ts index a9fe751ddab39b9e7381d23f1d016fc1a18b7791..5f405aa82462c07ae1234d5edd6b94870874ea72 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); } } @@ -516,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) { @@ -537,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"]); @@ -570,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"]); @@ -592,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"]); @@ -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/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 58e7765b7952b67007b31d14407726cd213460d0..0c52f0761182d59d46efc4b454e4881e30d645bb 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; @@ -35,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(); @@ -133,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)); } @@ -170,6 +177,16 @@ export class Ts2Panda { let funcSignature = Ts2Panda.getFuncSignature(pg); 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; if (CmdOptions.isDebugMode()) { @@ -189,6 +206,7 @@ export class Ts2Panda { variables, sourceFile, sourceCode, + typeInfo ); let catchTables = generateCatchTables(pg.getCatchMap()); catchTables.forEach((catchTable) => { diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b3aa893c36af081b3770dbd5e828c9bae84e503 --- /dev/null +++ b/ts2panda/src/typeChecker.ts @@ -0,0 +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 symbol: ts.Symbol = this.compiledTypeChecker.getSymbolAtLocation(nameNode); + let targetNode = symbol?.valueDeclaration; + if (targetNode) { + if (ts.isClassDeclaration(targetNode!)) { + let testClassType = new ClassType(targetNode, newExpressionFlag, nameNode); + } + } + // console.log(type.getSymbol()?.valueDeclaration); + }) + } + } +} diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts new file mode 100644 index 0000000000000000000000000000000000000000..53130340a2b4e2f38a0ded83f6ebff57c2778d37 --- /dev/null +++ b/ts2panda/src/typeRecorder.ts @@ -0,0 +1,78 @@ +/* + * 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 ts from "typescript"; +import { + BaseType, + PrimitiveType +} from "./base/typeSystem"; + +export class TypeRecorder { + private static instance: TypeRecorder; + private type2Index: Map = new Map(); + private typeInfo: Array = new Array(); + private variable2Type: Map = new Map(); + + private constructor() {} + + public static getInstance() { + return TypeRecorder.instance; + } + + public static createInstance() { + TypeRecorder.instance = new TypeRecorder(); + } + + public addType2Index(typeNode: ts.Node, index: number) { + this.type2Index.set(typeNode, index); + } + + public setVariable2Type(variableNode: ts.Node, index: number) { + this.variable2Type.set(variableNode, index); + } + + public hasType(typeNode: ts.Node): boolean { + return this.type2Index.has(typeNode); + } + + public tryGetTypeIndex(typeNode: ts.Node): number { + if (this.type2Index.has(typeNode)) { + return this.type2Index.get(typeNode)!; + } else { + return -1; + } + } + + 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 { + return this.type2Index; + } + + public getTypeInfo(): Array { + return this.typeInfo; + } + + public getVariable2Type(): Map { + return this.variable2Type; + } +} \ No newline at end of file diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 966cb9191bab1bad699eff7fa377ce18dccad5d9..e43625b15b6c1b57867d2c8a43d3e126e0c2de91 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -33,6 +33,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 +43,14 @@ export abstract class Variable { this.name = name; this.vreg = undefined; this.name = name; + this.typeIndex = 77; } 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 { @@ -63,6 +68,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(); @@ -140,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); diff --git a/ts2panda/templates/diagnostic.ts.erb b/ts2panda/templates/diagnostic.ts.erb index a6df2d57301a1cf1c44f7573d347b324f96101de..795fda099aa820287af95bc61ec1e981a6c8638a 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) } diff --git a/ts2panda/templates/irnodes.ts.erb b/ts2panda/templates/irnodes.ts.erb index 40e6936c0e791ff33e6eb8a8075838784a55383e..2e73c9cee4799f148a372f65c730ebaa85e5d24f 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; @@ -201,6 +202,7 @@ export class VReg { constructor() { this.id = VReg.global_id++; + this.typeIndex = 0; // for debug purposes this.setStackTrace(null); @@ -225,6 +227,14 @@ export class VReg { return; } } + + getTypeIndex() { + return this.typeIndex; + } + + setTypeIndex(typeIndex: number) { + this.typeIndex = typeIndex; + } } export class Imm extends IRNode { diff --git a/ts2panda/tests/BUILD.gn b/ts2panda/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0414b6f11227ed5dcedaff78a67c7f5c6c278548 --- /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 ced5796134ec03244538dcf941ff095aac0de0b3..2484fba12f72d056f9d7f8f8cfd60b2428e128f4 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 0000000000000000000000000000000000000000..660e1b72b0f7c13b0d94e13c6d977f9c9d849239 --- /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 3f996596b15ade75a32263aefc44416d74d024f6..f80ba94f38de91a66973ce481b84a9d183e7914a 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 95a2fbb7d55e7e89f05dc24ca15ec981bb1b390e..c19a8a45ac9abc0ae11891857304c14977294318 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 0000000000000000000000000000000000000000..2534c932ac403bf59170da7d0c5023c5542f3aca --- /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 ae7b88840e62002d2b01653c51014fcfbc7065ab..8e15bd616b506d0b882c3f40469c50bb7a7033c8 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 0000000000000000000000000000000000000000..8c7f3a1ace370a42f0163b37159686fa137a7e63 --- /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 8f8b26ebe3c3dc5ddc585f610d487501c84381c1..3a466cfd114b46102ab56287f14aa22558ff1358 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 1d349b0d258b47f70e5fea1dccad02942eccd810..f7cdaa4e5a76581dcea683aac75c72b2a482399b 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 2f91e12fe66de11abb796a1a5b4043e8dc9fa5fd..7b4936bfb963ab8d8168a7662843abd750c74bc9 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 0000000000000000000000000000000000000000..54e54b96aebd3cbe3c0255090a54cede3a821be9 --- /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 f81909c89a93e13ef0e4a1b1591d11415ccabbe1..e2440dae8f625fdbedddb44c677902ffbd374fe7 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 cd6383d014bdf628007c7c99969f34063168e271..e8c3e842e31d3eab754ea7794cd90401bf32df9f 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 0000000000000000000000000000000000000000..64dfb2fadf762dc5640a6532a3e4e4cdc9f92c92 --- /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 0000000000000000000000000000000000000000..370d10e7513d809b564a4454704fa500aa7ea80d --- /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 0000000000000000000000000000000000000000..df76e7bc4713a6aef7618ad2756d750e5500ebea --- /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 0000000000000000000000000000000000000000..67f70a550c02fbf6b8dca64f5626341238864fc9 --- /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 541081e8ec93cc0d20e15eb691fef3da017bd848..f63f03003ca04eb641482c26644178d9c239fd3c 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 0000000000000000000000000000000000000000..22a0dc7e28c91d217d5c36ab1f2d24d4d60677bc --- /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 b926af8e466a645db1e3d046ebcd62525762cac4..cf56ba16dcb6661a287f3ab30e20858de80455e1 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 eb892c835f5b21e0b087f2c2092a32c299a79bdd..5654375b5f4b6f3b550ac4878bc8f21d5dc7fadb 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 95e69ebc3e24815bdc5eeaee6f66140b0cb7009a..186c2d2b94ee0fb304e09678151a00e546a450b1 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 0000000000000000000000000000000000000000..d504d517216e767050184b872da86058b5cac613 --- /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 0000000000000000000000000000000000000000..330849f16c42c742af3546c64df57037520de317 --- /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 bc5d49f7b2934f8bc099e6d5e84f60b013739c6e..1cb0b35c6eb70e3f037e55cf52a22b064dff9f64 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 4dfdab7984ae3e8ec7538ed72463e74ee76e2f7b..8016811d793d8d4a8b5fd2fa75cec4b643400470 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 19c42f89ab73ef153d40710d9de1361347eba14a..634973e7365d51fdc8d9562b28af96ec5a031220 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 f96187ca5891af62b14cbcc85909adb90796fe61..c380eeb24edc4ef22b22f3b0907cdc245c747cd6 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 0a35621cf62783eff8806dcee7705ff2bc5a3e35..93e4c6892f92706a3f3e0b402001c50878928801 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 3b2a4dde104160e3ca9c10c39cf29253dbfef853..85ef72aa12f4d374754159f3b406c591619b7950 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 f121dce9cb8e1380c25118740b539bcbdb6ee03f..9cbe527f94c0f08baa120bd7ecb7da256dfd1155 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 0000000000000000000000000000000000000000..ca308a2d4ab500aa1747f7b725feeb08395abb59 --- /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 7f5bc717baaa8d82f77191eb107e944b05fa7e92..6b52e9cfd53a7efd329d6433983a9a7427b86b30 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 93348bfc36fd2584a7c414501b454c3059855b85..374f6c7b400e99914b0a990da06c6c39d3c939f6 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 0000000000000000000000000000000000000000..bf2963edfe391d4f5de107272aa84d17aac06955 --- /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 0000000000000000000000000000000000000000..a62f826d80b0d40d2bcd1dff7772cb402702141e --- /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 9c4b77a7a3e0869990767f1e2a217eb81e9f727b..7528c8dffc7f7563c8cb206d207ba2482925b63a 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 2a04ef11be2fb9077577f19e787cc341f5c209f0..91cb0a12552ddbeb8bc9f6d36a41d59179eb884e 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 b280676bba1d3d7e8c84abc1a9a30706b34b2d08..7114b171ca7a779986ec16873710ca41846004b8 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 49f61826328634a409cd4c321aef40befb5ec1db..51f1082baf5d164c6d3aa6c89c2c0e367ba30fc3 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 0000000000000000000000000000000000000000..6e40c78dc991a3e256015c192268641805cc84d0 --- /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 224cb0b60089a113430508a66ebcd0b8c83ff9d8..19c0922233e51ecea0abe2d6a12139c5897529a8 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 0000000000000000000000000000000000000000..23c1b381797729234af10d8f805a957d3a6e3d98 --- /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 0000000000000000000000000000000000000000..edaef63e1b79281c261411e28c3387fee80ac22f --- /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 3be3b735be29ed85d2648905a1041961af71504f..0000000000000000000000000000000000000000 --- 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 de869a4650c04676d99d8d9b5c4ae9d2ffb19998..51d5dbb431c6c0fead44f04ac716a3816664c1ad 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 b4185ef75dfe70be3afdc8ba94ca133ac6570a9d..78718fbd04153cf6e76d43501172fa3fd9ebee47 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/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 8f131798fb1334cc8f335f1a0881c63b052004d8..3655037e2e2f61ab928922bbd3afb3f64b86a5e1 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -594,6 +594,42 @@ 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"); + std::vector elements; + 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::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)); + } +} + static panda::pandasm::Function ParseFunction(const Json::Value &function) { auto pandaFunc = GetFunctionDefintion(function); @@ -607,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); @@ -705,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); diff --git a/ts2panda/ts2abc_config.gni b/ts2panda/ts2abc_config.gni index a86ae8032eb04bbe23de2eeda0b41bf5a8f4c4cb..3455351b7205cb6657710bfb510ec732cc386e8d 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}/" ] + } +}