From 9260bfce9606ff909ce44067dae1213ba9f2deed Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Fri, 23 Sep 2022 21:06:02 +0800 Subject: [PATCH 01/59] Enable non-null expression in es2abc Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5U2RF Test: test262, parser tests, compiler tests Signed-off-by: xucheng46 Change-Id: Icba218d483b46422c466b9bcb7e4f57c14fbed71 --- es2panda/ir/ts/tsNonNullExpression.cpp | 5 ++++- es2panda/ir/ts/tsNonNullExpression.h | 2 +- ...ts-test-non-null-expression-1-expected.txt | 1 + .../ts-test-non-null-expression-1.ts | 21 +++++++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1.ts diff --git a/es2panda/ir/ts/tsNonNullExpression.cpp b/es2panda/ir/ts/tsNonNullExpression.cpp index 06f51f77c7..e43b52db35 100644 --- a/es2panda/ir/ts/tsNonNullExpression.cpp +++ b/es2panda/ir/ts/tsNonNullExpression.cpp @@ -29,7 +29,10 @@ void TSNonNullExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNonNullExpression"}, {"expression", expr_}}); } -void TSNonNullExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNonNullExpression::Compile(compiler::PandaGen *pg) const +{ + expr_->Compile(pg); +} checker::Type *TSNonNullExpression::Check([[maybe_unused]] checker::Checker *checker) const { diff --git a/es2panda/ir/ts/tsNonNullExpression.h b/es2panda/ir/ts/tsNonNullExpression.h index 9f278f49f7..5d0e858c83 100644 --- a/es2panda/ir/ts/tsNonNullExpression.h +++ b/es2panda/ir/ts/tsNonNullExpression.h @@ -40,7 +40,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; diff --git a/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1-expected.txt new file mode 100644 index 0000000000..86f1793aff --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1-expected.txt @@ -0,0 +1 @@ +ts-test-non-null-expression-1 diff --git a/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1.ts b/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1.ts new file mode 100644 index 0000000000..f239bef2d8 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/expressions/ts-test-non-null-expression-1.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + a : string = "ts-test-non-null-expression-1"; +} +var x : C = new C(); +print(x!.a) \ No newline at end of file -- Gitee From 64565123e0cc6631add21fea91b38c54b881e782 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Tue, 13 Sep 2022 10:32:30 +0800 Subject: [PATCH 02/59] Add HowToWriteProtoForAssemblyStuff.md Signed-off-by: zhangrengao Change-Id: Iad80fb375ca1a61bd6ee088fe63b95846812691c --- merge_abc/HowToWriteProtoForAssemblyStuff.md | 281 +++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 merge_abc/HowToWriteProtoForAssemblyStuff.md diff --git a/merge_abc/HowToWriteProtoForAssemblyStuff.md b/merge_abc/HowToWriteProtoForAssemblyStuff.md new file mode 100644 index 0000000000..83f76ebe34 --- /dev/null +++ b/merge_abc/HowToWriteProtoForAssemblyStuff.md @@ -0,0 +1,281 @@ +# How To Write Proto For Assembly + +## 消息格式 + +``` +syntax = "proto3" // 指定版本信息 +message Test // message为关键字,作用为定义一种消息类型 +{ + string test = 1; +} +``` + +消息由字段组合而成 +``` +限定修饰符 数据类型 字段名称 = 唯一编号标签值 +``` + +## 限定修饰符说明 + +### required + +required 在发送消息之前必须设置该字段的值。对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。 + +``` +syntax = "proto3" +message Test +{ + required string test = 1; +} +``` + +### repeated + +repeated 代表可重复,我们可以理解为数组 + +``` +syntax = "proto3" +message Test +{ + string test = 1; +} + +message TestArr +{ + repeated Test arr = 1; +} +``` + +### optional + +optional 表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。如果无法识别,则忽略该字段,消息中的其它字段正常处理。 + +## 数据类型 + +| proto类型 | C++类型 | 备注 | +|:-----------|:---------------|:------------| +|double |double | 64位浮点数 +|float |float | 32位浮点数 +|int32 |int32 | 32位整数 +|int64 |int64 | 64位整数 +|uint32 |uint32 | 32位无符号整数 +|uint64 |uint64 | 64位无符号整数 +|sint32 |int32 | 32位整数,处理负数效率比int32更高 +|sint32 |sint64 | 64位整数,处理负数效率比int64更高 +|fixed32 | uint32 | 总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。 +|fixed64 | uint64 | 总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。 +|sfixed32 | int32 | 总是4个字节 +|sfixed64 | int64 | 总是8个字节 +|bool | bool | 布尔类型 +|string | string | 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本 +|bytes | string | 处理多字节的语言字符、如中文 +|enum | enum | 枚举(proto2 从1开始,proto3从0开始) +|message | object of class | 自定义的消息类型 + + +## 字段名称 + +protobuf建议以下划线命名而非驼峰式 + +## 唯一的编号标签 + +代表每个字段的一个唯一的编号标签,在同一个消息里不可以重复。这些编号标签用与在消息二进制格式中标识你的字段,并且消息一旦定义就不能更改。需要说明的是标签在1到15范围的采用一个字节进行编码,所以通常将标签1到15用于频繁发生的消息字段。编号标签大小的范围是1到229。此外不能使用protobuf系统预留的编号标签(19000 ~19999) + +## import + +protobuf 接口文件可以像C语言的h文件一个,分离为多个,在需要的时候通过 import导入需要对文件。其行为和C语言的#include或者java的import的行为大致相同。 + +## enum + +``` +syntax = "proto3" // 指定版本信息 +enum COLOR +{ + RED = 0; + BLUE = 1; + YELLOW = 2; +} + +message Test // message为关键字,作用为定义一种消息类型 +{ + string test = 1; + COLOR type = 2; +} +``` + +## package + +``` +syntax = "proto3" // 指定版本信息 + +package tutorial; + +message Test // message为关键字,作用为定义一种消息类型 +{ + string test = 1; +} +``` + +## oneof + +message 包含许多可选字段,并且最多只能同时设置其中一个字段,则可以使用 oneof 功能强制执行此行为并节省内存 + +# Assembly对应Proto + +## class\struct + +protobuf中将类型信息结构化处理,通过自定义消息message结构对C++中class或struct进行解析处理 + +C++ +``` +struct Ins { + size_t line_number = 0; + uint32_t column_number = 0; + std::string whole_line = ""; // TODO(mbolshov): redundant given file and line_number + size_t bound_left = 0; + size_t bound_right = 0; +} +``` + +proto +``` +message DebuginfoIns { + uint64 lineNumber = 1; + uint32 columnNumber = 2; + bytes wholeLine = 3; + uint64 boundLeft = 4; + uint64 boundRight = 5; +} +``` + + +## enum + +protobuf中存在enum类型,proto2 从1开始,proto3从0开始 + +对于Assembly中的转换,优化序列化速度,通过uint32位直接进行转换: + +C++ +``` +class Value { +public: + enum class Type { + U1, + I8, + U8, + I16, + U16, + I32, + U32, + I64, + U64, + F32, + F64, + STRING, + STRING_NULLPTR, + RECORD, + METHOD, + ENUM, + ANNOTATION, + ARRAY, + VOID, + METHOD_HANDLE, + UNKNOWN + }; + ... +} + +``` + + +proto +``` +message Value { + uint32 type = 1; +} +``` +## inheritance + +protobuf中message无继承信息,开发者自己实现继承信息 + +C++ +``` +class Value { +... +} + +class ArrayValue : public Value { +... +} +``` + +proto +``` + +message Value { + uint32 type = 1; +} + +message ArrayValue { + Value father = 1; +} + +``` + +## std::variant + +通过oneof关键字实现std::variant + +C++ +``` +std::variant value_; +``` + +proto +``` +oneof value { + uint64 valueU64 = 2; + float valueFloat = 3; + double valueDouble = 4; + bytes valueStr = 5; + Type valueType = 6; + AnnotationData valueAnno = 7; +} +``` + +## unique_ptr + +查看源码中的变量关系,通过oneof实现智能指针 + +C++ +``` +class Value { +} + +class ArrayValue { +} + +class ScalarValue { +} + +std::unique_ptr value_; +``` + +proto +``` +message Value { +} + +message ScalarValue { + Value father = 1; +} + +message ArrayValue { + Value father = 1; +} + +oneof value { + ScalarValue scalar = 2; + ArrayValue array = 3; +} +``` -- Gitee From 3ec72dc3a2efca2ea61fcdc48a8271c50bd249f1 Mon Sep 17 00:00:00 2001 From: zhuoli Date: Tue, 18 Oct 2022 16:59:06 +0800 Subject: [PATCH 03/59] Fix duplicate build target on linux/mac of es2abc on host Signed-off-by: zhuoli Change-Id: If2ccd097b8a6c2c21790f893ca978fce5e757d9c --- es2panda/BUILD.gn | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 075eedd3e8..853d2a3494 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -515,15 +515,28 @@ if (is_mac) { } } -ohos_copy("build_es2abc_for_hap") { - deps = [ ":es2panda(${host_toolchain})" ] - es2abc_root_out_dir = - get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") - es2abc_target_out_dir = - get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") - - sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] - outputs = [ "${es2abc_target_out_dir}/build/bin/es2abc" ] +if (is_linux) { + ohos_copy("build_es2abc_for_hap") { + deps = [ ":es2panda(${host_toolchain})" ] + es2abc_root_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") + es2abc_target_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") + + sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] + outputs = [ "${es2abc_target_out_dir}/build/bin/es2abc" ] + } +} else if (is_mac) { + ohos_copy("build_es2abc_for_hap") { + deps = [ ":es2panda(${host_toolchain})" ] + es2abc_root_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") + es2abc_target_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") + + sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] + outputs = [ "${es2abc_target_out_dir}/build-mac/bin/es2abc" ] + } } group("es2panda_build") { -- Gitee From b0c33ee807e6136ccaa5caf0592c8caf950dbbd3 Mon Sep 17 00:00:00 2001 From: wangyantian Date: Mon, 26 Sep 2022 20:57:19 +0800 Subject: [PATCH 04/59] Support parsing of namespace export declaration Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5TAHP Test: parser test, compiler test, test262 Signed-off-by: wangyantian Change-Id: I566cb5234b3e00218e43c59d18c3554cb5507a52 --- es2panda/BUILD.gn | 1 + es2panda/ir/astNodeMapping.h | 1 + .../ir/ts/tsNamespaceExportDeclaration.cpp | 45 ++++++ es2panda/ir/ts/tsNamespaceExportDeclaration.h | 55 +++++++ es2panda/parser/parserImpl.cpp | 15 +- es2panda/parser/parserImpl.h | 2 + es2panda/parser/statementParser.cpp | 40 ++++- ...-namespace-export-declaration-expected.txt | 145 ++++++++++++++++++ .../test-namespace-export-declaration.d.ts | 17 ++ es2panda/test/runner.py | 20 ++- es2panda/util/helpers.cpp | 14 ++ es2panda/util/helpers.h | 2 + 12 files changed, 343 insertions(+), 14 deletions(-) create mode 100644 es2panda/ir/ts/tsNamespaceExportDeclaration.cpp create mode 100644 es2panda/ir/ts/tsNamespaceExportDeclaration.h create mode 100644 es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt create mode 100644 es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 075eedd3e8..70080d0361 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -154,6 +154,7 @@ es2panda_src = [ "ir/ts/tsModuleBlock.cpp", "ir/ts/tsModuleDeclaration.cpp", "ir/ts/tsNamedTupleMember.cpp", + "ir/ts/tsNamespaceExportDeclaration.cpp", "ir/ts/tsNeverKeyword.cpp", "ir/ts/tsNonNullExpression.cpp", "ir/ts/tsNullKeyword.cpp", diff --git a/es2panda/ir/astNodeMapping.h b/es2panda/ir/astNodeMapping.h index 0ae3acc429..5ca835452b 100644 --- a/es2panda/ir/astNodeMapping.h +++ b/es2panda/ir/astNodeMapping.h @@ -114,6 +114,7 @@ _(TS_PARAMETER_PROPERTY, TSParameterProperty) \ _(TS_MODULE_DECLARATION, TSModuleDeclaration) \ _(TS_IMPORT_EQUALS_DECLARATION, TSImportEqualsDeclaration) \ + _(TS_NAMESPACE_EXPORT_DECLARATION, TSNamespaceExportDeclaration) \ _(TS_FUNCTION_TYPE, TSFunctionType) \ _(TS_CONSTRUCTOR_TYPE, TSConstructorType) \ _(TS_TYPE_ALIAS_DECLARATION, TSTypeAliasDeclaration) \ diff --git a/es2panda/ir/ts/tsNamespaceExportDeclaration.cpp b/es2panda/ir/ts/tsNamespaceExportDeclaration.cpp new file mode 100644 index 0000000000..4ed6c17818 --- /dev/null +++ b/es2panda/ir/ts/tsNamespaceExportDeclaration.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tsNamespaceExportDeclaration.h" + +#include +#include + +namespace panda::es2panda::ir { + +void TSNamespaceExportDeclaration::Iterate(const NodeTraverser &cb) const +{ + cb(id_); +} + +void TSNamespaceExportDeclaration::Dump(ir::AstDumper *dumper) const +{ + dumper->Add({{"type", "TSNamespaceExportDeclaration"}, {"id", id_}}); +} + +void TSNamespaceExportDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} + +checker::Type *TSNamespaceExportDeclaration::Check([[maybe_unused]] checker::Checker *checker) const +{ + return nullptr; +} + +void TSNamespaceExportDeclaration::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) +{ + id_ = std::get(cb(id_))->AsIdentifier(); +} + +} // namespace panda::es2panda::ir \ No newline at end of file diff --git a/es2panda/ir/ts/tsNamespaceExportDeclaration.h b/es2panda/ir/ts/tsNamespaceExportDeclaration.h new file mode 100644 index 0000000000..24f2aa8e4c --- /dev/null +++ b/es2panda/ir/ts/tsNamespaceExportDeclaration.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef ES2PANDA_IR_TS_NAMESPACE_EXPORT_DECLARATION_H +#define ES2PANDA_IR_TS_NAMESPACE_EXPORT_DECLARATION_H + +#include + +namespace panda::es2panda::compiler { +class PandaGen; +} // namespace panda::es2panda::compiler + +namespace panda::es2panda::checker { +class Checker; +class Type; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::ir { + +class TSNamespaceExportDeclaration : public Statement { +public: + explicit TSNamespaceExportDeclaration(Identifier *id) + : Statement(AstNodeType::TS_NAMESPACE_EXPORT_DECLARATION), id_(id) + { + } + + const Identifier *Id() const + { + return id_; + } + + void Iterate(const NodeTraverser &cb) const override; + void Dump(ir::AstDumper *dumper) const override; + void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; + void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; + +private: + Identifier *id_; +}; +} // namespace panda::es2panda::ir + +#endif \ No newline at end of file diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index bb76705438..09a79b3c26 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -103,18 +104,11 @@ namespace panda::es2panda::parser { ParserImpl::ParserImpl(ScriptExtension extension) : program_(extension), context_(&program_) {} -template -bool IsSuffix(T const &filename, T const &suffix) -{ - return (filename.length() > suffix.length()) && - (filename.rfind(suffix) == (filename.length() - suffix.length())); -} - std::unique_ptr ParserImpl::InitLexer(const std::string &fileName, const std::string &source) { bool isDtsFile = false; if (Extension() == ScriptExtension::TS) { - isDtsFile = IsSuffix(fileName, std::string(".d.ts")); + isDtsFile = util::Helpers::FileExtensionIs(fileName, ".d.ts"); } program_.SetSource(source, fileName, isDtsFile); auto lexer = std::make_unique(&context_); @@ -3547,4 +3541,9 @@ void ParserImpl::AddHotfixHelper(util::Hotfix *hotfixHelper) program_.AddHotfixHelper(hotfixHelper); } +bool ParserImpl::IsDtsFile() const +{ + return program_.IsDtsFile(); +} + } // namespace panda::es2panda::parser diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 7476ac673e..16d2929ce9 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -188,6 +188,7 @@ public: { return program_.Allocator(); } + bool IsDtsFile() const; private: bool IsStartOfMappedType() const; @@ -439,6 +440,7 @@ private: ir::TSImportEqualsDeclaration *ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc, bool isExport = false); + ir::TSNamespaceExportDeclaration *ParseTsNamespaceExportDeclaration(const lexer::SourcePosition &startLoc); ir::TSModuleBlock *ParseTsModuleBlock(); ir::BlockStatement *ParseFunctionBody(); ir::BlockStatement *ParseBlockStatement(); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index b70db86492..fb0b61b1f8 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,7 @@ void ParserImpl::CheckDeclare() case lexer::TokenType::KEYW_CLASS: { break; } - case lexer::TokenType::LITERAL_IDENT: + case lexer::TokenType::LITERAL_IDENT: { if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE || lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE || lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL || @@ -111,6 +112,7 @@ void ParserImpl::CheckDeclare() } [[fallthrough]]; + } default: { ThrowSyntaxError("Unexpected token."); } @@ -132,6 +134,8 @@ bool ParserImpl::IsLabelFollowedByIterationStatement() lexer_->NextToken(); return IsLabelFollowedByIterationStatement(); } + + [[fallthrough]]; } default: return false; @@ -429,6 +433,33 @@ ir::TSImportEqualsDeclaration *ParserImpl::ParseTsImportEqualsDeclaration(const return importEqualsDecl; } +ir::TSNamespaceExportDeclaration *ParserImpl::ParseTsNamespaceExportDeclaration(const lexer::SourcePosition &startLoc) +{ + if (!IsDtsFile()) { + ThrowSyntaxError("namespace export declaration is only supported in TypeScript '.d.ts'"); + } + ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS); + lexer_->NextToken(); // eat as keyword + if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NAMESPACE) { + ThrowSyntaxError("'namespace' expected"); + } + lexer_->NextToken(); // eat namespace keyword + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + ThrowSyntaxError("identifier expected"); + } + + auto *id = AllocNode(lexer_->GetToken().Ident(), Allocator()); + id->SetRange(lexer_->GetToken().Loc()); + lexer_->NextToken(); // eat identifier + + auto *namespaceExportDecl = AllocNode(id); + namespaceExportDecl->SetRange({startLoc, lexer_->GetToken().End()}); + + ConsumeSemicolon(namespaceExportDecl); + + return namespaceExportDecl; +} + ir::TSModuleBlock *ParserImpl::ParseTsModuleBlock() { if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { @@ -2496,6 +2527,13 @@ ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags, [[fallthrough]]; } + case lexer::TokenType::LITERAL_IDENT: { + if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { + return ParseTsNamespaceExportDeclaration(startLoc); + } + + [[fallthrough]]; + } default: { // export [var] id ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators)); diff --git a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt new file mode 100644 index 0000000000..f6b2d8c17d --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt @@ -0,0 +1,145 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "TSDeclareFunction", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "isPrime", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 16, + "column": 28 + }, + "end": { + "line": 16, + "column": 34 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 25 + }, + "end": { + "line": 16, + "column": 26 + } + } + } + ], + "returnType": { + "type": "TSBooleanKeyword", + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 45 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 45 + } + } + }, + { + "type": "TSNamespaceExportDeclaration", + "id": { + "type": "Identifier", + "name": "mathLib", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 29 + } + } +} diff --git a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts new file mode 100644 index 0000000000..79d7ad4637 --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function isPrime(x: number): boolean; +export as namespace mathLib; \ No newline at end of file diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 76526b230e..8b79f1de9f 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -145,6 +145,9 @@ class Test: def log_cmd(self, cmd): self.reproduce += "\n" + ' '.join(cmd) + def get_path_to_expected(self): + return "%s-expected.txt" % (path.splitext(self.path)[0]) + def run(self, runner): cmd = runner.cmd_prefix + [runner.es2panda, "--dump-ast"] cmd.extend(self.flags) @@ -156,7 +159,7 @@ class Test: out, err = process.communicate() self.output = out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore") - expected_path = "%s-expected.txt" % (path.splitext(self.path)[0]) + expected_path = self.get_path_to_expected(); try: with open(expected_path, 'r') as fp: expected = fp.read() @@ -496,13 +499,13 @@ class RegressionRunner(Runner): def __init__(self, args): Runner.__init__(self, args, "Regresssion") - def add_directory(self, directory, extension, flags): + def add_directory(self, directory, extension, flags, func=Test): glob_expression = path.join( self.test_root, directory, "*.%s" % (extension)) files = glob(glob_expression) files = fnmatch.filter(files, self.test_root + '**' + self.args.filter) - self.tests += list(map(lambda f: Test(f, flags), files)) + self.tests += list(map(lambda f: func(f, flags), files)) def test_path(self, src): return src @@ -807,7 +810,7 @@ class CompilerTest(Test): process = subprocess.Popen(run_abc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() self.output = out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore") - expected_path = "%s-expected.txt" % (path.splitext(self.path)[0]) + expected_path = self.get_path_to_expected() try: with open(expected_path, 'r') as fp: expected = fp.read() @@ -823,6 +826,12 @@ class CompilerTest(Test): return self +class TSDeclarationTest(Test): + def get_path_to_expected(self): + file_name = self.path[:self.path.find(".d.ts")] + return "%s-expected.txt" % file_name + + def main(): args = get_args() @@ -835,7 +844,8 @@ def main(): ["--parse-only", "--module", "--extension=ts"]) runner.add_directory("parser/ts/type_checker", "ts", ["--parse-only", "--enable-type-check", "--module", "--extension=ts"]) - + runner.add_directory("parser/ts/cases/declaration", "d.ts", + ["--parse-only", "--module", "--extension=ts"], TSDeclarationTest) runners.append(runner) if args.test262: diff --git a/es2panda/util/helpers.cpp b/es2panda/util/helpers.cpp index afe9ed62ab..14f909b075 100644 --- a/es2panda/util/helpers.cpp +++ b/es2panda/util/helpers.cpp @@ -122,6 +122,20 @@ int64_t Helpers::GetIndex(const util::StringView &str) return value; } +bool Helpers::FileExtensionIs(std::string_view filePath, std::string_view extension) +{ + return filePath.length() > extension.length() && Helpers::EndsWith(filePath, extension); +} + +bool Helpers::EndsWith(std::string_view str, std::string_view suffix) +{ + if (str.length() < suffix.length()) { + return false; + } + size_t expectPos = str.length() - suffix.length(); + return str.find(suffix, expectPos) == expectPos; +} + std::string Helpers::ToString(double number) { std::string str; diff --git a/es2panda/util/helpers.h b/es2panda/util/helpers.h index 35144bce15..9321178fda 100644 --- a/es2panda/util/helpers.h +++ b/es2panda/util/helpers.h @@ -56,6 +56,8 @@ public: static bool IsIndex(double number); static int64_t GetIndex(const util::StringView &str); + static bool FileExtensionIs(std::string_view filePath, std::string_view extension); + static bool EndsWith(std::string_view str, std::string_view suffix); static std::string ToString(double number); static util::StringView ToStringView(ArenaAllocator *allocator, double number); static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number); -- Gitee From 6dad3b05c086a7e6d8c64d2117774ad41bd0b3c7 Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Tue, 18 Oct 2022 15:19:29 +0800 Subject: [PATCH 05/59] Fix step into async function Issue:I5WC0Z Signed-off-by: ctw-ian Change-Id: I2e50bdcf6c63e4090b51d3b1e0215bc07bcd194c --- es2panda/compiler/core/function.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index b9a4bce84f..5fb0ba8c80 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -156,7 +156,9 @@ static void CompileFunction(PandaGen *pg) pg->StoreAccToLexEnv(pg->RootNode(), funcParamScope->Find(funcParamScope->NameVar()->Name()), true); } + pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION); pg->FunctionEnter(); + pg->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION); CompileFunctionParameterDeclaration(pg, decl); const ir::AstNode *body = decl->Body(); -- Gitee From 453cc8534bc524efe369dfa8289d8def4e665eda Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Thu, 13 Oct 2022 17:22:54 +0800 Subject: [PATCH 06/59] Fix several bugs of es2abc 1.Fix spill-restore in range register allocator 2.Fix missing mandatory parameters in FunctionParamScope Issue:I5VW0W Signed-off-by: ctw-ian Change-Id: I38d3d986992da2b160cbb1c6288d9bc01b73a114 --- es2panda/binder/binder.cpp | 1 + es2panda/compiler/core/pandagen.cpp | 4 +- es2panda/compiler/core/regAllocator.cpp | 9 +- es2panda/compiler/core/regAllocator.h | 1 + ...arameter-with-default-value-1-expected.txt | 2 + .../parameter-with-default-value-1.js | 13 + .../test-spill-fill-2-expected.txt | 1 + .../js/regAllocator/test-spill-fill-2.js | 267 ++++++++++++++++++ 8 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 es2panda/test/compiler/js/parameter/parameter-with-default-value-1-expected.txt create mode 100644 es2panda/test/compiler/js/parameter/parameter-with-default-value-1.js create mode 100644 es2panda/test/compiler/js/regAllocator/test-spill-fill-2-expected.txt create mode 100644 es2panda/test/compiler/js/regAllocator/test-spill-fill-2.js diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 47b85b9967..1c6f0022a7 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -609,6 +609,7 @@ void Binder::AddMandatoryParam(const std::string_view &name) auto &funcParams = scope_->AsFunctionVariableScope()->ParamScope()->Params(); funcParams.insert(funcParams.begin(), param); + scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param}); scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param}); } diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 88a863f84f..3488d439f9 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1180,11 +1180,11 @@ void PandaGen::CallThis(const ir::AstNode *node, VReg startReg, size_t argCount) default: { int64_t actualArgs = argCount - 1; if (actualArgs <= util::Helpers::MAX_INT8) { - rra_.Emit(node, thisReg, argCount + 1, 0, actualArgs, thisReg); + rra_.Emit(node, thisReg, argCount, 0, actualArgs, thisReg); break; } - rra_.Emit(node, thisReg, argCount + 1, actualArgs, thisReg); + rra_.Emit(node, thisReg, argCount, actualArgs, thisReg); break; } } diff --git a/es2panda/compiler/core/regAllocator.cpp b/es2panda/compiler/core/regAllocator.cpp index 7e9ce2ca72..88613e85bd 100644 --- a/es2panda/compiler/core/regAllocator.cpp +++ b/es2panda/compiler/core/regAllocator.cpp @@ -89,6 +89,11 @@ void RegAllocatorBase::Restore(IRNode *ins) Add(ins->Node(), spillReg, origin); } +void RegAllocatorBase::ClearSpillMap() +{ + spillMap_.clear(); +} + // RegAllocator void RegAllocator::Run(IRNode *ins) @@ -122,7 +127,7 @@ void RegAllocator::Run(IRNode *ins) Restore(ins); } - spillMap_.clear(); + ClearSpillMap(); } void RegAllocator::Run(IRNode *ins, int64_t typeIndex) @@ -176,6 +181,8 @@ void RangeRegAllocator::Run(IRNode *ins, VReg rangeStart, size_t argCount) while (spillIndex_ != 0) { Restore(ins); } + + ClearSpillMap(); } } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/regAllocator.h b/es2panda/compiler/core/regAllocator.h index dd00e365b7..bd1bb17fa8 100644 --- a/es2panda/compiler/core/regAllocator.h +++ b/es2panda/compiler/core/regAllocator.h @@ -151,6 +151,7 @@ protected: VReg Spill(IRNode *ins, VReg reg); void Restore(IRNode *ins); + void ClearSpillMap(); VReg spillIndex_ {0}; VReg regEnd_ {0}; diff --git a/es2panda/test/compiler/js/parameter/parameter-with-default-value-1-expected.txt b/es2panda/test/compiler/js/parameter/parameter-with-default-value-1-expected.txt new file mode 100644 index 0000000000..1191247b6d --- /dev/null +++ b/es2panda/test/compiler/js/parameter/parameter-with-default-value-1-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/js/parameter/parameter-with-default-value-1.js b/es2panda/test/compiler/js/parameter/parameter-with-default-value-1.js new file mode 100644 index 0000000000..e749bcbacd --- /dev/null +++ b/es2panda/test/compiler/js/parameter/parameter-with-default-value-1.js @@ -0,0 +1,13 @@ +class A { + constructor(param) { + this.c = param; + } + + a(b = this.c) { + print(b); + } +} + +let aa = new A(1); +aa.a(); +aa.a(2); diff --git a/es2panda/test/compiler/js/regAllocator/test-spill-fill-2-expected.txt b/es2panda/test/compiler/js/regAllocator/test-spill-fill-2-expected.txt new file mode 100644 index 0000000000..190a18037c --- /dev/null +++ b/es2panda/test/compiler/js/regAllocator/test-spill-fill-2-expected.txt @@ -0,0 +1 @@ +123 diff --git a/es2panda/test/compiler/js/regAllocator/test-spill-fill-2.js b/es2panda/test/compiler/js/regAllocator/test-spill-fill-2.js new file mode 100644 index 0000000000..66a845537c --- /dev/null +++ b/es2panda/test/compiler/js/regAllocator/test-spill-fill-2.js @@ -0,0 +1,267 @@ +function xx() { + let a = undefined; + let aa = undefined; + let aaa = undefined; + let aaaa = undefined; + let aaaaa = undefined; + let aaaaaa = undefined; + let aaaaaaa = undefined; + let aaaaaaaa = undefined; + let b = undefined; + let bb = undefined; + let bbb = undefined; + let aaabab = undefined; + let aaaabab = undefined; + let aaaabaab = undefined; + let aaaaabaab = undefined; + let aaaaaabaab = undefined; + let ab = undefined; + let aba = undefined; + let abaa = undefined; + let abaaa = undefined; + let abaaaa = undefined; + let aabaaaa = undefined; + let aabaaaaa = undefined; + let aaabaaaaa = undefined; + let bbbbb = undefined; + let bbbbbb = undefined; + let bbbb = undefined; + let aaaba = undefined; + let aaaaba = undefined; + let aaaabaa = undefined; + let aaaaabaa = undefined; + let aaaaaabaa = undefined; + let c = undefined; + let ac = undefined; + let aac = undefined; + let aaac = undefined; + let aaaac = undefined; + let aaaaac = undefined; + let aaaaaac = undefined; + let aaaaaaac = undefined; + let aaaaaaaca = undefined; + let bc = undefined; + let bbc = undefined; + let bbbc = undefined; + let aaabcab = undefined; + let aaaababc = undefined; + let aaaabaabc = undefined; + let aaaaabaabc = undefined; + let aaaaaabaabc = undefined; + let abc = undefined; + let abca = undefined; + let abcaa = undefined; + let abacaa = undefined; + let abacaaa = undefined; + let aabaacaa = undefined; + let aabaacaaa = undefined; + let aaabcaaaaa = undefined; + let bbbbcb = undefined; + let bbbbcbb = undefined; + let bbbcb = undefined; + let aacaba = undefined; + let aaaabca = undefined; + let aaaacbaa = undefined; + let aaaaabcaa = undefined; + let aaaaacabaa = undefined; + let add = undefined; + let aadd = undefined; + let aaadd = undefined; + let aaaadd = undefined; + let aaaaadd = undefined; + let aaaaaadd = undefined; + let aaaaaadda = undefined; + let aaaaaaadda = undefined; + let bdd = undefined; + let bbdd = undefined; + let bbbdd = undefined; + let aaababdd = undefined; + let aaaabddab = undefined; + let aaaabddaab = undefined; + let aaaaaddbaab = undefined; + let aaaaaabddaab = undefined; + let ddab = undefined; + let abdda = undefined; + let abadda = undefined; + let abaddaa = undefined; + let abaaddaa = undefined; + let aabaaddaa = undefined; + let aabaaaddaa = undefined; + let aaabaaaddaa = undefined; + let bbbddbb = undefined; + let bbbddbbb = undefined; + let bbddbb = undefined; + let aaaddba = undefined; + let aaaddaba = undefined; + let aaaabaadd = undefined; + let aaaaabaadd = undefined; + let aaaaaabaadd = undefined; + let cdd = undefined; + let acdd = undefined; + let aacdd = undefined; + let aaacdd = undefined; + let aaaacddd = undefined; + let aaaaacddd = undefined; + let aaaaaacddd = undefined; + let aaaaaaacdd = undefined; + let aaaaaaacadd = undefined; + let bcdd = undefined; + let bbcdd = undefined; + let bbbcdd = undefined; + let aaabcabdd = undefined; + let aaaababcdd = undefined; + let aaaabaabcdd = undefined; + let aaaaabaabcdd = undefined; + let aaaaaabaabcdd = undefined; + let abcdd = undefined; + let abcdda = undefined; + let abcaddda = undefined; + let abacaddda = undefined; + let abacaadda = undefined; + let aabaacddaa = undefined; + let aabaacaaadd = undefined; + let aaabcaaaaadd = undefined; + let bbbbcbdd = undefined; + let bbbbcbbdd = undefined; + let bbbcbdd = undefined; + let aacabdda = undefined; + let aaaabcadd = undefined; + let aaaacbadda = undefined; + let aaaaabcaadd = undefined; + let aaaaacabddaa = undefined; + let ae = undefined; + let aaee = undefined; + let aaaee = undefined; + let aaaae = undefined; + let aaaaea = undefined; + let aaaaaea = undefined; + let aaaaaeaa = undefined; + let aaaaaaeaa = undefined; + let be = undefined; + let bbe = undefined; + let bbeb = undefined; + let aaabeab = undefined; + let aaaaebab = undefined; + let aaaabaeab = undefined; + let aaaaaebaab = undefined; + let aaaaaaebaab = undefined; + let abe = undefined; + let aeba = undefined; + let abeaa = undefined; + let abaeaa = undefined; + let abaeaaa = undefined; + let aabaeaaa = undefined; + let aabaaeaaa = undefined; + let aaabeaaaaa = undefined; + let bbbbeb = undefined; + let bbbbebb = undefined; + let bbbeb = undefined; + let aaaeba = undefined; + let aaaeaba = undefined; + let aaaeabaa = undefined; + let aaaeaabaa = undefined; + let aaaaeaabaa = undefined; + let ce = undefined; + let aec = undefined; + let aaec = undefined; + let aaaec = undefined; + let aaaeac = undefined; + let aaaaeac = undefined; + let aaaaeaac = undefined; + let aaaaaeaac = undefined; + let aaaaaeaaca = undefined; + let bce = undefined; + let bbce = undefined; + let bbbec = undefined; + let aaabceab = undefined; + let aaaabaebc = undefined; + let aaaabaeabc = undefined; + let aaaaabaeabc = undefined; + let aaaaaabeaabc = undefined; + let abce = undefined; + let abcea = undefined; + let abcaea = undefined; + let abacaea = undefined; + let abacaeaa = undefined; + let aabaeacaa = undefined; + let aabaaceaaa = undefined; + let aaabcaaeaaa = undefined; + let bbbbecb = undefined; + let bbbbcbeb = undefined; + let bbbceb = undefined; + let aacaeba = undefined; + let aaaaebca = undefined; + let aaaacbaea = undefined; + let aaaaabecaa = undefined; + let aaaaaceabaa = undefined; + let adde = undefined; + let aaded = undefined; + let aaaedd = undefined; + let aaaaedd = undefined; + let aaaaeadd = undefined; + let aaaaeaadd = undefined; + let aaaaaeadda = undefined; + let aaaaaaeadda = undefined; + let bded = undefined; + let bbedd = undefined; + let bbbded = undefined; + let aaababedd = undefined; + let aaaabdedab = undefined; + let aaaabddaeab = undefined; + let aaaaaeddbaab = undefined; + let aaaaaabeddaab = undefined; + let ddabe = undefined; + let abdeda = undefined; + let abadeda = undefined; + let abadedaa = undefined; + let abaaddeaa = undefined; + let aabaadedaa = undefined; + let aabaaaeddaa = undefined; + let aaabaaadedaa = undefined; + let bbbddebb = undefined; + let bbbddbebb = undefined; + let bbddebb = undefined; + let aaaddeba = undefined; + let aaaddaeba = undefined; + let aaaabeaadd = undefined; + let aaaaabaeadd = undefined; + let aaaaaabaeadd = undefined; + let cdde = undefined; + let acdde = undefined; + let aacdde = undefined; + let aaacdde = undefined; + let aaaacdded = undefined; + let aaaaacdded = undefined; + let aaaaaacdded = undefined; + let aaaaaaacdde = undefined; + let aaaaaaacadde = undefined; + let bcedd = undefined; + let bbcedd = undefined; + let bbbcedd = undefined; + let aaabceabdd = undefined; + let aaaabaebcdd = undefined; + let aaaabaaebcdd = undefined; + let aaaaabaaebcdd = undefined; + let aaaaaabaaebcdd = undefined; + let abcdde = undefined; + let abcddae = undefined; + let abcadddea = undefined; + let abacadddea = undefined; + let abacaaddae = undefined; + let aabaacddaae = undefined; + let aabaacaaadde = undefined; + let aaabcaaaaadde = undefined; + let bbbbcbdde = undefined; + let bbbbcbbdde = undefined; + let bbbcbdde = undefined; + let aacabddae = undefined; + let aaaabcadde = undefined; + let aaaacbaddae = undefined; + let aaaaabcaadde = undefined; + let aaaaacabddaae = {a: function b(c) { + print(c); + }}; + aaaaacabddaae.a(123); +} + +xx(); -- Gitee From 8e03ee4fa989d2e74e2680279a0f30ff73546613 Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Tue, 6 Sep 2022 10:58:17 +0800 Subject: [PATCH 07/59] Support serializing proto bin && record-name && record-name testing in ts2abc Signed-off-by: gavin1012_hw Change-Id: I63bab0c084d4b1bbd22dd8cb5f39dc70165266ce --- es2panda/aot/options.cpp | 3 +- merge_abc/src/assemblyFileLocationProto.cpp | 12 ++-- merge_abc/src/assemblyFileLocationProto.h | 3 +- merge_abc/src/assemblyFunctionProto.cpp | 2 +- merge_abc/src/assemblyLabelProto.cpp | 2 +- merge_abc/src/assemblyRecordProto.cpp | 2 +- test262/run_sunspider.py | 39 +++++++++--- ts2panda/src/cmdOptions.ts | 13 ++++ ts2panda/src/compilerDriver.ts | 17 +++--- ts2panda/src/index.ts | 32 +++++++--- ts2panda/src/pandasm.ts | 16 +---- ts2panda/src/ts2panda.ts | 20 ++++++- ts2panda/tests/builtIns.test.ts | 2 +- ts2panda/tests/commonjs.test.ts | 6 +- ts2panda/tests/esmodule.test.ts | 2 +- ts2panda/tests/expression/arguments.test.ts | 4 +- ts2panda/tests/expression/commalist.test.ts | 2 +- .../expression/functionExpression.test.ts | 38 ++++++------ ts2panda/tests/expression/thisKeyWord.test.ts | 2 +- ts2panda/tests/hoist.test.ts | 18 +++--- ts2panda/tests/lexenv.test.ts | 30 +++++----- .../statements/functionDeclaration.test.ts | 19 +++--- .../statements/variableDeclaration.test.ts | 8 +-- ts2panda/tests/types/array.test.ts | 12 ++-- ts2panda/tests/types/class.test.ts | 16 ++--- ts2panda/tests/types/function.test.ts | 10 ++-- ts2panda/tests/types/object.test.ts | 4 +- ts2panda/tests/types/primitives.test.ts | 30 +++++----- ts2panda/tests/types/union.test.ts | 8 +-- ts2panda/tests/utils/base.ts | 10 ++-- ts2panda/ts2abc/ts2abc.cpp | 60 +++++++------------ ts2panda/ts2abc/ts2abc_options.h | 2 +- 32 files changed, 243 insertions(+), 201 deletions(-) diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index d581dab53a..5d189f5203 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -149,7 +149,8 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg base64Output("base64Output", false, "output panda file content as base64 to std out"); panda::PandArg sourceFile("source-file", "", "specify the file path info recorded in generated abc"); - panda::PandArg outputProto("outputProto", "", "compiler proto serialize binary output (.proto)"); + panda::PandArg outputProto("outputProto", "", + "specify the output name for serializd protobuf file (.protoBin)"); panda::PandArg opCacheFile("cache-file", "", "cache file for incremental compile"); panda::PandArg opNpmModuleEntryList("npm-module-entry-list", "", "entry list file for module compile"); panda::PandArg opMergeAbc("merge-abc", false, "Compile as merge abc"); diff --git a/merge_abc/src/assemblyFileLocationProto.cpp b/merge_abc/src/assemblyFileLocationProto.cpp index 9f4a0f23bd..e3ef08e976 100644 --- a/merge_abc/src/assemblyFileLocationProto.cpp +++ b/merge_abc/src/assemblyFileLocationProto.cpp @@ -21,14 +21,16 @@ void FileLocation::Serialize(const panda::pandasm::FileLocation &location, proto protoLocation.set_wholeline(location.whole_line); protoLocation.set_boundleft(location.bound_left); protoLocation.set_boundright(location.bound_right); + protoLocation.set_linenumber(location.line_number); protoLocation.set_isdefined(location.is_defined); } -void FileLocation::Deserialize(const protoPanda::FileLocation &protoLocation, panda::pandasm::FileLocation &location) +void FileLocation::Deserialize(const protoPanda::FileLocation &protoLocation, + std::optional &location) { - location.whole_line = protoLocation.wholeline(); - location.bound_left = protoLocation.boundleft(); - location.bound_right = protoLocation.boundright(); - location.is_defined = protoLocation.isdefined(); + std::string wholeLine = protoLocation.wholeline(); + panda::pandasm::FileLocation fileLocation(wholeLine, protoLocation.boundleft(), protoLocation.boundright(), + protoLocation.linenumber(), protoLocation.isdefined()); + location = fileLocation; } } // panda::proto diff --git a/merge_abc/src/assemblyFileLocationProto.h b/merge_abc/src/assemblyFileLocationProto.h index 83afe39022..2c13264974 100644 --- a/merge_abc/src/assemblyFileLocationProto.h +++ b/merge_abc/src/assemblyFileLocationProto.h @@ -23,7 +23,8 @@ namespace panda::proto { class FileLocation { public: static void Serialize(const panda::pandasm::FileLocation &location, protoPanda::FileLocation &protoLocation); - static void Deserialize(const protoPanda::FileLocation &protoLocation, panda::pandasm::FileLocation &location); + static void Deserialize(const protoPanda::FileLocation &protoLocation, + std::optional &location); }; } // panda::proto #endif diff --git a/merge_abc/src/assemblyFunctionProto.cpp b/merge_abc/src/assemblyFunctionProto.cpp index 0b56bf70f5..f5f9972365 100644 --- a/merge_abc/src/assemblyFunctionProto.cpp +++ b/merge_abc/src/assemblyFunctionProto.cpp @@ -161,7 +161,7 @@ void Function::Deserialize(const protoPanda::Function &protoFunction, panda::pan SourceLocation::Deserialize(protoFunction.bodylocation(), function.body_location); if (protoFunction.has_filelocation()) { - FileLocation::Deserialize(protoFunction.filelocation(), function.file_location.value()); + FileLocation::Deserialize(protoFunction.filelocation(), function.file_location); } function.SetFunctionKind(static_cast(protoFunction.function_kind())); } diff --git a/merge_abc/src/assemblyLabelProto.cpp b/merge_abc/src/assemblyLabelProto.cpp index f355a80490..63b18cefc1 100644 --- a/merge_abc/src/assemblyLabelProto.cpp +++ b/merge_abc/src/assemblyLabelProto.cpp @@ -31,7 +31,7 @@ void Label::Deserialize(const protoPanda::Label &protoLabel, panda::pandasm::Lab label.name = protoLabel.name(); if (protoLabel.has_filelocation()) { protoPanda::FileLocation protoLocation = protoLabel.filelocation(); - FileLocation::Deserialize(protoLocation, label.file_location.value()); + FileLocation::Deserialize(protoLocation, label.file_location); } } } // panda::proto diff --git a/merge_abc/src/assemblyRecordProto.cpp b/merge_abc/src/assemblyRecordProto.cpp index cfd7d34d44..9409ff1297 100644 --- a/merge_abc/src/assemblyRecordProto.cpp +++ b/merge_abc/src/assemblyRecordProto.cpp @@ -56,7 +56,7 @@ void Record::Deserialize(const protoPanda::Record &protoRecord, panda::pandasm:: record.source_file = protoRecord.sourcefile(); if (protoRecord.has_filelocation()) { const auto &protoLocation = protoRecord.filelocation(); - FileLocation::Deserialize(protoLocation, record.file_location.value()); + FileLocation::Deserialize(protoLocation, record.file_location); } } } // panda::proto diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 0a06caa4bd..30dbaca4bd 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -230,9 +230,23 @@ class ArkProgram(): output_file = os.path.splitext(os.path.join(BASE_OUT_DIR, os.path.split(dependency)[1]))[0] output_abc = f"{output_file}.abc" + proto_bin_file = f"{output_file}.bin" + output_abc_name = os.path.basename(output_abc) + frontend_tool = self.ark_frontend_binary - cmd_args = [frontend_tool, dependency, '--output', output_abc, - '--module'] + merge_abc_binary = self.args.merge_abc_binary + merge_abc_mode = self.merge_abc_mode + + if merge_abc_mode != "0": + cmd_args = [frontend_tool, dependency, '--outputProto', + proto_bin_file, '--module', '--merge-abc'] + proc = subprocess.call(cmd_args) + cmd_args = [merge_abc_binary, '--input', proto_bin_file, '--suffix', + "bin", '--outputFilePath', BASE_OUT_DIR, '--output', + output_abc_name] + else: + cmd_args = [frontend_tool, dependency, '--output', output_abc, + '--module', '--merge-abc'] proc = subprocess.Popen(cmd_args) proc.wait() @@ -262,8 +276,13 @@ class ArkProgram(): if self.ark_frontend == ARK_FRONTEND_LIST[0]: mod_opt_index = 3 - cmd_args = ['node', '--expose-gc', frontend_tool, - js_file, '-o', out_file] + if merge_abc_mode != "0": + # '--opt-level=0' is added due to failure in optimizer, should be removed later + cmd_args = ['node', '--expose-gc', frontend_tool, js_file, + '--output-proto', proto_bin_file, '--opt-level=0'] + else: + cmd_args = ['node', '--expose-gc', frontend_tool, + js_file, '-o', out_file] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "-m") self.module = True @@ -271,7 +290,7 @@ class ArkProgram(): mod_opt_index = 1 if merge_abc_mode != "0": cmd_args = [frontend_tool, '--outputProto', - proto_bin_file, js_file] + proto_bin_file, js_file, '--merge-abc'] else: cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), '--function-threads=' + @@ -293,13 +312,15 @@ class ArkProgram(): abc_file = os.path.abspath(f'{js_dir}/{abc_file}') if self.abc_file.find(abc_file) < 0: self.abc_file += f':{abc_file}' - retcode = exec_command(cmd_args) self.abc_cmd = cmd_args - if self.ark_frontend == ARK_FRONTEND_LIST[1] and merge_abc_mode != "0": + if merge_abc_mode != "0": + proc = subprocess.call(cmd_args) cmd_args = [merge_abc_binary, '--input', proto_bin_file, '--suffix', "bin", '--outputFilePath', file_dir, '--output', proto_abc_file] retcode = exec_command(cmd_args) + else: + retcode = exec_command(cmd_args) return retcode def compile_aot(self): @@ -353,6 +374,8 @@ class ArkProgram(): f'--aot-file={file_name_pre}', f'{file_name_pre}.abc'] + record_name = os.path.splitext(os.path.split(self.js_file)[1])[0] + cmd_args.insert(-1, f'--entry-point={record_name}') retcode = exec_command(cmd_args) if retcode: print_command(cmd_args) @@ -388,6 +411,8 @@ class ArkProgram(): cmd_args = [self.ark_tool, ICU_PATH, f'{file_name_pre}.abc'] + record_name = os.path.splitext(os.path.split(self.js_file)[1])[0] + cmd_args.insert(-1, f'--entry-point={record_name}') retcode = exec_command(cmd_args) if retcode: print_command(cmd_args) diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index bf19d72cd5..94b151eaff 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -51,6 +51,8 @@ const ts2pandaOptions = [ { name: 'expression-watch-toolchain', type: String, defaultValue: "es2panda", description: "Specify the tool chain used to transform the expression" }, { name: 'source-file', type: String, defaultValue: "", description: "specify the file path info recorded in generated abc" }, { name: 'generate-tmp-file', type: Boolean, defaultValue: false, description: "whether to generate intermediate temporary files"}, + { name: 'record-name', type: String, defaultValue: "", description: "specify the record name." }, + { name: 'output-proto', type: String, defaultValue: "", description: "specify the output name for serializd protobuf file (.protoBin)" }, ] @@ -209,6 +211,13 @@ export class CmdOptions { return outputFile; } + static getRecordName(): string { + if (!this.options) { + return ""; + } + return this.options["record-name"]; + } + static getTimeOut(): Number { if (!this.options) { return 0; @@ -315,6 +324,10 @@ export class CmdOptions { return this.options["generate-tmp-file"]; } + static getOutputproto(): string { + return this.options["output-proto"]; + } + // @ts-ignore static parseUserCmd(args: string[]): ts.ParsedCommandLine | undefined { this.options = commandLineArgs(ts2pandaOptions, { partial: true }); diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index b4c4413c6b..2897861533 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -67,6 +67,7 @@ export class CompilerDriver { static srcNode: ts.SourceFile | undefined = undefined; static isTsFile: boolean = false; private fileName: string; + private recordName: string; private passes: Pass[] = []; private compilationUnits: PandaGen[]; pendingCompilationUnits: PendingCompilationUnit[]; @@ -76,8 +77,9 @@ export class CompilerDriver { private needDumpHeader: boolean = true; private ts2abcProcess: any = undefined; - constructor(fileName: string) { + constructor(fileName: string, recordName: string) { this.fileName = fileName; + this.recordName = recordName; // register passes here this.passes = [ new CacheExpander(), @@ -184,6 +186,7 @@ export class CompilerDriver { listenErrorEvent(ts2abcProc); try { + Ts2Panda.dumpRecord(ts2abcProc, this.recordName); Ts2Panda.dumpCmdOptions(ts2abcProc); Ts2Panda.dumpRecordName(ts2abcProc, getRecordName(CompilerDriver.srcNode)); @@ -367,20 +370,20 @@ export class CompilerDriver { name = "func_main_0"; } else if (ts.isConstructorDeclaration(node)) { let classNode = node.parent; - name = this.getInternalNameForCtor(classNode, node); + return this.getInternalNameForCtor(classNode, node); } else { let funcNode = node; name = (recorder.getScopeOfNode(funcNode)).getFuncName(); if (name == '') { if ((ts.isFunctionDeclaration(node) && hasExportKeywordModifier(node) && hasDefaultKeywordModifier(node)) || ts.isExportAssignment(findOuterNodeOfParenthesis(node))) { - return 'default'; + return `${this.recordName}.default`; } - return `#${this.getFuncId(funcNode)}#`; + return `${this.recordName}.#${this.getFuncId(funcNode)}#`; } if (name == "func_main_0") { - return `#${this.getFuncId(funcNode)}#${name}`; + return `${this.recordName}.#${this.getFuncId(funcNode)}#${name}`; } let funcNameMap = recorder.getFuncNameMap(); @@ -397,7 +400,7 @@ export class CompilerDriver { name = `#${this.getFuncId(funcNode)}#` } } - return name; + return `${this.recordName}.${name}`; } getInternalNameForCtor(node: ts.ClassLikeDeclaration, ctor: ts.ConstructorDeclaration) { @@ -406,7 +409,7 @@ export class CompilerDriver { if (name.lastIndexOf(".") != -1) { name = `#${this.getFuncId(ctor)}#` } - return name; + return `${this.recordName}.${name}`; } writeBinaryFile(pandaGen: PandaGen) { diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 62cfa8cbb5..26eb031a6d 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -45,7 +45,7 @@ function checkIsGlobalDeclaration(sourceFile: ts.SourceFile) { function generateDTs(node: ts.SourceFile, options: ts.CompilerOptions) { let outputBinName = getOutputBinName(node); - let compilerDriver = new CompilerDriver(outputBinName); + let compilerDriver = new CompilerDriver(outputBinName, getRecordName(node)); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); compilerDriver.compile(node); compilerDriver.showStatistics(); @@ -90,7 +90,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { let outputBinName = getOutputBinName(node); - let compilerDriver = new CompilerDriver(outputBinName); + let compilerDriver = new CompilerDriver(outputBinName, getRecordName(node)); compilerDriver.compileForSyntaxCheck(node); return node; } @@ -118,7 +118,7 @@ function main(fileNames: string[], options: ts.CompilerOptions) { node = transformCommonjsModule(node); } let outputBinName = getOutputBinName(node); - let compilerDriver = new CompilerDriver(outputBinName); + let compilerDriver = new CompilerDriver(outputBinName, getRecordName(node)); CompilerDriver.srcNode = node; setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); compilerDriver.compile(node); @@ -177,6 +177,17 @@ function getDtsFiles(libDir: string): string[] { return dtsFiles; } +function getRecordName(node: ts.SourceFile): string { + let recordName = CmdOptions.getRecordName(); + + if (recordName == "") { + let outputBinName = getOutputBinName(node); + recordName = path.basename(outputBinName, path.extname(outputBinName)); + } + + return recordName; +} + function specifyCustomLib(customLib) { Compiler.Options.Default["lib"] = customLib; let curFiles = fs.readdirSync(__dirname); @@ -203,12 +214,14 @@ function specifyCustomLib(customLib) { const stopWatchingStr = "####"; const watchAbcFileDefaultTimeOut = 10; const watchFileName = "watch_expressions"; +const watchOutputFileName = "Base64Output"; // this path is only available in sdk const es2abcBinaryPath = path["join"](__dirname, "..", "bin", path.sep); const es2abcBinaryName = /^win/.test(require('os').platform()) ? "es2abc.exe" : "es2abc"; const es2abcBase64Input = "--base64Input"; const es2abcDebuggerEvaluateFlag = "--debugger-evaluate-expression"; const es2abcBase64Output = "--base64Output"; +// need to specify the record name as 'Base64Output' in es2abc's commandline; cancel the opMergeAbc option function callEs2pandaToolChain(ideInputStr: string) { let commandLine = "\"" + es2abcBinaryPath + es2abcBinaryName + "\" " + es2abcBase64Input + " \"" + ideInputStr @@ -306,7 +319,7 @@ function compileWatchExpression(jsFileName: string, errorMsgFileName: string, op return (node: ts.SourceFile) => { if (path.basename(node.fileName) == fileName) { node = sourceFile; } let outputBinName = getOutputBinName(node); - let compilerDriver = new CompilerDriver(outputBinName); + let compilerDriver = new CompilerDriver(outputBinName, watchOutputFileName); compilerDriver.compileForSyntaxCheck(node); return node; } @@ -331,7 +344,7 @@ function compileWatchExpression(jsFileName: string, errorMsgFileName: string, op node = ts.factory.updateSourceFile(node, newStatements); } let outputBinName = getOutputBinName(node); - let compilerDriver = new CompilerDriver(outputBinName); + let compilerDriver = new CompilerDriver(outputBinName, watchOutputFileName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); compilerDriver.compile(node); return node; @@ -347,10 +360,11 @@ function launchWatchEvaluateDeamon(parsed: ts.ParsedCommandLine | undefined) { console.log("startWatchingSuccess supportTimeout"); return; } - let deamonFilePrefix = CmdOptions.getEvaluateDeamonPath() + path.sep + watchFileName; - let jsFileName = deamonFilePrefix + ".js"; - let abcFileName = deamonFilePrefix + ".abc"; - let errorMsgFileName = deamonFilePrefix + ".err"; + let deamonJSFilePrefix = CmdOptions.getEvaluateDeamonPath() + path.sep + watchFileName; + let deamonABCFilePrefix = CmdOptions.getEvaluateDeamonPath() + path.sep + watchOutputFileName; + let jsFileName = deamonJSFilePrefix + ".js"; + let abcFileName = deamonABCFilePrefix + ".abc"; + let errorMsgFileName = deamonJSFilePrefix + ".err"; if (fs.existsSync(jsFileName)) { console.log("watchFileServer has been initialized supportTimeout"); diff --git a/ts2panda/src/pandasm.ts b/ts2panda/src/pandasm.ts index 50231d9279..bc12caea96 100644 --- a/ts2panda/src/pandasm.ts +++ b/ts2panda/src/pandasm.ts @@ -115,24 +115,10 @@ export class Function { export class Record { public name: string; - public whole_line: string; - public bound_left: number; - public bound_right: number; - public line_number: number; public metadata: Metadata; - constructor( - name: string, - whole_line: string, - bound_left: number, - bound_right: number, - line_number: number - ) { + constructor(name: string) { this.name = name; - this.whole_line = whole_line; - this.bound_left = bound_left; - this.bound_right = bound_right; - this.line_number = line_number; this.metadata = new Metadata(); } } diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index a97288f3f3..271a015000 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -37,7 +37,8 @@ import { ModuleRecord, NamespaceImportEntry, RegularImportEntry, - Signature + Signature, + Record } from "./pandasm"; import { generateCatchTables } from "./statement/tryStatement"; import { @@ -237,6 +238,8 @@ export class Ts2Panda { "opt_log_level": CmdOptions.getOptLogLevel(), "display_typeinfo": CmdOptions.getDisplayTypeinfo(), "is_dts_file": isGlobalDeclare(), + "output-proto": CmdOptions.isOutputproto(), + "proto-name": CmdOptions.getProtoName(), "record_type": enableRecordType }; let jsonOpt = JSON.stringify(options, null, 2); @@ -247,6 +250,19 @@ export class Ts2Panda { ts2abc.stdio[3].write(jsonOpt + '\n'); } + static dumpRecord(ts2abc: any, recordName: string): void { + let record = { + "t": JsonType.record, + "rb": new Record(recordName) + } + let jsonRecord = escapeUnicode(JSON.stringify(record, null, 2)); + jsonRecord = "$" + jsonRecord.replace(dollarSign, '#$') + "$"; + if (CmdOptions.isEnableDebugLog()) { + Ts2Panda.jsonString += jsonRecord; + } + ts2abc.stdio[3].write(jsonRecord + '\n'); + } + // @ts-ignore static dumpInstTypeMap(pg: PandaGen): any { let insts = pg.getInsns(); @@ -356,7 +372,7 @@ export class Ts2Panda { } typeInfo = Ts2Panda.dumpInstTypeMap(pg); - if (funcName == "func_main_0") { + if (funcName.endsWith("func_main_0")) { let exportedTypes = PandaGen.getExportedTypes(); let declareddTypes = PandaGen.getDeclaredTypes(); if (exportedTypes.size != 0) { diff --git a/ts2panda/tests/builtIns.test.ts b/ts2panda/tests/builtIns.test.ts index 2ec85828da..d17b95e933 100644 --- a/ts2panda/tests/builtIns.test.ts +++ b/ts2panda/tests/builtIns.test.ts @@ -45,7 +45,7 @@ describe("FunctionToStringTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compileAfter(`function foo() {return 123;}\nfunction bar() {return 321;}\n`, 'toStringTest.js'); CmdOptions.needRecordSourceCode = () => {return false}; - let pandaGen = snippetCompiler.getPandaGenByName('foo'); + let pandaGen = snippetCompiler.getPandaGenByName('UnitTest.foo'); let expected = "function foo() {return 123;}"; expect(pandaGen.getSourceCode() == expected).to.be.true; }) diff --git a/ts2panda/tests/commonjs.test.ts b/ts2panda/tests/commonjs.test.ts index 60c24b23ce..f814112ec4 100644 --- a/ts2panda/tests/commonjs.test.ts +++ b/ts2panda/tests/commonjs.test.ts @@ -49,7 +49,7 @@ describe("CommonJsTest", function () { CmdOptions.isCommonJs = () => {return false}; let funcMainInsns = snippetCompiler.getGlobalInsns(); let expected = [ - new Definefunc(new Imm(0), '#1#', new Imm(5)), + new Definefunc(new Imm(0), 'UnitTest.#1#', new Imm(5)), new Sta(new VReg()), new Lda(new VReg()), new Sta(new VReg()), @@ -74,7 +74,7 @@ describe("CommonJsTest", function () { snippetCompiler.compileCommonjs(`let a = require('a.js')`, 'cjs.js'); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`let a = require('a.js')`), 0, undefined); CmdOptions.isCommonJs = () => {return false}; - let execInsns = snippetCompiler.getPandaGenByName('#1#')!.getInsns(); + let execInsns = snippetCompiler.getPandaGenByName('UnitTest.#1#')!.getInsns(); let requirePara = new VReg(); let requireReg = new VReg(); let moduleRequest = new VReg(); @@ -97,7 +97,7 @@ describe("CommonJsTest", function () { snippetCompiler.compileCommonjs(`let a = 1; exports.a = a;`, 'cjs.js'); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`let a = 1; exports.a = a;`), 0, undefined); CmdOptions.isCommonJs = () => {return false}; - let execInsns = snippetCompiler.getPandaGenByName('#1#')!.getInsns(); + let execInsns = snippetCompiler.getPandaGenByName('UnitTest.#1#')!.getInsns(); let exportsPara = new VReg(); let exportsReg = new VReg(); let tmpReg = new VReg(); diff --git a/ts2panda/tests/esmodule.test.ts b/ts2panda/tests/esmodule.test.ts index ff7e32c244..e73c64d565 100644 --- a/ts2panda/tests/esmodule.test.ts +++ b/ts2panda/tests/esmodule.test.ts @@ -49,7 +49,7 @@ describe("ExportDeclaration", function () { let classReg = new VReg(); let expected = [ new Mov(new VReg(), new VReg()), - new Defineclasswithbuffer(new Imm(0), "#1#C", "_0", new Imm(0), new VReg()), + new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#C", "_0", new Imm(0), new VReg()), new Sta(classReg), new Lda(classReg), new Stmodulevar(new Imm(0)), diff --git a/ts2panda/tests/expression/arguments.test.ts b/ts2panda/tests/expression/arguments.test.ts index f509b3966f..60d84a95ab 100644 --- a/ts2panda/tests/expression/arguments.test.ts +++ b/ts2panda/tests/expression/arguments.test.ts @@ -47,7 +47,7 @@ describe("arguments Keyword", function () { new Ldobjbyindex(new Imm(0), new Imm(0)), new Returnundefined() ]; - let functionPg = snippetCompiler.getPandaGenByName("foo"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.foo"); let insns = functionPg!.getInsns(); expect(checkInstructions(insns, expected)).to.be.true; @@ -68,7 +68,7 @@ describe("arguments Keyword", function () { new Ldobjbyindex(new Imm(0), new Imm(0)), new Returnundefined() ]; - let functionPg = snippetCompiler.getPandaGenByName("foo"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.foo"); let insns = functionPg!.getInsns(); expect(checkInstructions(insns, expected)).to.be.true; diff --git a/ts2panda/tests/expression/commalist.test.ts b/ts2panda/tests/expression/commalist.test.ts index 41d44eb25b..6c00a01211 100644 --- a/ts2panda/tests/expression/commalist.test.ts +++ b/ts2panda/tests/expression/commalist.test.ts @@ -72,7 +72,7 @@ describe("CommaListExpression", function () { let insns = snippetCompiler.getGlobalInsns(); let expected = [ new Mov(new VReg(), new VReg()), - new Defineclasswithbuffer(new Imm(0), "#1#Test", "_0", new Imm(0), new VReg()), + new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#Test", "_0", new Imm(0), new VReg()), new Sta(new VReg()), new Lda(new VReg()), new Sttoglobalrecord(new Imm(1), "Test"), diff --git a/ts2panda/tests/expression/functionExpression.test.ts b/ts2panda/tests/expression/functionExpression.test.ts index d434f440ae..b4cd1c8e7a 100644 --- a/ts2panda/tests/expression/functionExpression.test.ts +++ b/ts2panda/tests/expression/functionExpression.test.ts @@ -71,7 +71,7 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "test") { + if (pg.internalName == "UnitTest.test") { expect(checkInstructions(pg.getInsns(), expected_func), "check func insns").to.be.true; checkCount++; } @@ -89,15 +89,15 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "a") { + if (pg.internalName == "UnitTest.a") { checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('a'); + expect(insns.operands[1]).to.equal('UnitTest.a'); checkCount++; } }); @@ -117,15 +117,15 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "a") { + if (pg.internalName == "UnitTest.a") { checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('a'); + expect(insns.operands[1]).to.equal('UnitTest.a'); checkCount++; } }); @@ -146,15 +146,15 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "a") { + if (pg.internalName == "UnitTest.a") { checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('a'); + expect(insns.operands[1]).to.equal('UnitTest.a'); checkCount++; } }); @@ -183,16 +183,16 @@ describe("compileFunctionExpression", function () { ]; pandaGens.forEach((pg) => { - if (pg.internalName == "p") { + if (pg.internalName == "UnitTest.p") { expect(checkInstructions(pg.getInsns(), expected_func), "check arrow func insns").to.be.true; checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('p'); + expect(insns.operands[1]).to.equal('UnitTest.p'); checkCount++; } }); @@ -289,15 +289,15 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "a") { + if (pg.internalName == "UnitTest.a") { expect(checkInstructions(pg.getInsns(), expected_func), "check generator func insns").to.be.true; checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('a'); + expect(insns.operands[1]).to.equal('UnitTest.a'); checkCount++; } }); @@ -352,15 +352,15 @@ describe("compileFunctionExpression", function () { let checkCount = 0; pandaGens.forEach((pg) => { - if (pg.internalName == "a") { + if (pg.internalName == "UnitTest.a") { expect(checkInstructions(pg.getInsns(), expected_func), "check async func insns").to.be.true; checkCount++; } - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { pg.getInsns().forEach((insns) => { if (insns instanceof Definefunc) { - expect(insns.operands[1]).to.equal('a'); + expect(insns.operands[1]).to.equal('UnitTest.a'); checkCount++; } }); diff --git a/ts2panda/tests/expression/thisKeyWord.test.ts b/ts2panda/tests/expression/thisKeyWord.test.ts index 9762e99121..c1ae227b88 100644 --- a/ts2panda/tests/expression/thisKeyWord.test.ts +++ b/ts2panda/tests/expression/thisKeyWord.test.ts @@ -51,7 +51,7 @@ describe("ThisKeyword", function () { it("this in function scope", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("function a() {this}"); - let functionPg = snippetCompiler.getPandaGenByName("a"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let functionScope = functionPg!.getScope(); let insns = compileMainSnippet("this;", pandaGen, functionScope); let expected = [ diff --git a/ts2panda/tests/hoist.test.ts b/ts2panda/tests/hoist.test.ts index 5542972dc6..30c227a420 100644 --- a/ts2panda/tests/hoist.test.ts +++ b/ts2panda/tests/hoist.test.ts @@ -86,7 +86,7 @@ describe("HoistTest", function () { let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new Definefunc(new Imm(0), "a", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.a", new Imm(0)), new Stglobalvar(new Imm(1), "a"), new Returnundefined() ] @@ -101,7 +101,7 @@ describe("HoistTest", function () { let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new Definefunc(new Imm(0), "#2#a", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.#2#a", new Imm(0)), new Stglobalvar(new Imm(1), "a"), new Returnundefined() ] @@ -117,7 +117,7 @@ describe("HoistTest", function () { let insns = snippetCompiler.getGlobalInsns(); let expected = [ - new Definefunc(new Imm(0), "a", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.a", new Imm(0)), new Stglobalvar(new Imm(1), "a"), new Ldai(new Imm(1)), new Stglobalvar(new Imm(2), "a"), @@ -132,7 +132,7 @@ describe("HoistTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {var a = 1;}`); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`function a() {var a = 1;}`), 0, undefined); - let funcPg = snippetCompiler.getPandaGenByName("a"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let insns = funcPg!.getInsns(); let a = new VReg(); @@ -152,11 +152,11 @@ describe("HoistTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`function a() {function b() {}};`); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`function a() {function b() {}};`), 0, undefined); - let funcPg = snippetCompiler.getPandaGenByName("a"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let insns = funcPg!.getInsns(); let a = new VReg(); let expected = [ - new Definefunc(new Imm(0), "b", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.b", new Imm(0)), new Sta(a), new Returnundefined() @@ -170,7 +170,7 @@ describe("HoistTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`a = 1; let a;`); - let funcPg = snippetCompiler.getPandaGenByName("func_main_0"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let insns = funcPg!.getInsns(); let idReg = new VReg(); let expected = [ @@ -189,7 +189,7 @@ describe("HoistTest", function () { a = 1; let a; }`); - let funcPg = snippetCompiler.getPandaGenByName("b"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.b"); let insns = funcPg!.getInsns(); let idReg = new VReg(); @@ -209,7 +209,7 @@ describe("HoistTest", function () { a = 1; let a; }`); - let funcPg = snippetCompiler.getPandaGenByName("func_main_0"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let insns = funcPg!.getInsns(); let idReg = new VReg(); diff --git a/ts2panda/tests/lexenv.test.ts b/ts2panda/tests/lexenv.test.ts index 5c52068929..c5d6e49463 100644 --- a/ts2panda/tests/lexenv.test.ts +++ b/ts2panda/tests/lexenv.test.ts @@ -104,7 +104,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { it("test CompilerDriver.scanFunctions-with-empty", function () { let source: string = ``; let sourceFile = creatAstFromSnippet(source); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); let globalScope = new GlobalScope(sourceFile); let recorder = new Recorder(sourceFile, globalScope, compilerDriver, false, false, true); recorder.record(); @@ -132,7 +132,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { var funcExpression = function() { } `; let sourceFile = creatAstFromSnippet(source); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); let globalScope = new GlobalScope(sourceFile); let recorder = new Recorder(sourceFile, globalScope, compilerDriver, false, false, true); recorder.record(); @@ -179,7 +179,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { let source: string = ` `; let sourceFile = creatAstFromSnippet(source); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); let globalScope = new GlobalScope(sourceFile); let recorder = new Recorder(sourceFile, globalScope, compilerDriver, false, false, true); @@ -203,7 +203,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { var funcExt = function() { } `; let sourceFile = creatAstFromSnippet(source); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); let globalScope = new GlobalScope(sourceFile); let recorder = new Recorder(sourceFile, globalScope, compilerDriver, false, false, true); @@ -257,7 +257,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { }))) `; let sourceFile = creatAstFromSnippet(source); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); let globalScope = new GlobalScope(sourceFile); let recorder = new Recorder(sourceFile, globalScope, compilerDriver, false, false, true); @@ -403,7 +403,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { let expected_main = [ new Lda(new VReg()), new Stglobalvar(new Imm(0), "outer"), - new Definefunc(new Imm(1), "func", new Imm(0)), + new Definefunc(new Imm(1), "UnitTest.func", new Imm(0)), new Stglobalvar(new Imm(2), "func"), new Ldai(new Imm(1)), new Stglobalvar(new Imm(3), "outer"), @@ -417,9 +417,9 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { ]; pandaGens.forEach((pg) => { - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { expect(checkInstructions(pg.getInsns(), expected_main)).to.be.true; - } else if (pg.internalName == "func") { + } else if (pg.internalName == "UnitTest.func") { expect(checkInstructions(pg.getInsns(), expected_func)).to.be.true; } }) @@ -438,7 +438,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { let pandaGens = compileAllSnippet(source, passes); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`class C {}; export {C}`), 0, undefined); let expected_main = [ - new Definefunc(new Imm(0), "func", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.func", new Imm(0)), new Stglobalvar(new Imm(1), "func"), // global.func = func_func_1 new Ldai(new Imm(1)), // value = 1 new Sttoglobalrecord(new Imm(2), "outer"), @@ -455,11 +455,11 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { pandaGens.forEach((pg) => { let scope = pg.getScope(); - if (pg.internalName == "func_main_0") { + if (pg.internalName == "UnitTest.func_main_0") { expect(checkInstructions(pg.getInsns(), expected_main), "check main insns").to.be.true; 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") { + } else if (pg.internalName == "UnitTest.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); @@ -500,7 +500,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { new Lda(new VReg()), new Stlexvar(new Imm(0), new Imm(1)), new Lda(new VReg()), - new Definefunc(new Imm(0), "#1#", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.#1#", new Imm(0)), // returnStatement new Sta(new VReg()), new Lda(new VReg()), @@ -536,13 +536,13 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { snippetCompiler.compile(source, passes); // check compile result! - let outerPg = snippetCompiler.getPandaGenByName("outer"); + let outerPg = snippetCompiler.getPandaGenByName("UnitTest.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).getNumLexEnv(), "number of lexvar at outer scope").to.be.equal(2); - let anonymousPg = snippetCompiler.getPandaGenByName("#1#"); + let anonymousPg = snippetCompiler.getPandaGenByName("UnitTest.#1#"); let anonymousScope = anonymousPg!.getScope(); let anonymousA = anonymousScope!.findLocal("a"); let searchRlt = anonymousScope!.find("a"); @@ -551,7 +551,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { expect(anonymousA, "no a in anonymous function").to.be.undefined; // 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 globalPg = snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let globalScope = globalPg!.getScope(); let globalA = globalScope!.findLocal("a"); expect(globalA instanceof GlobalVariable, "globalA is GlobalVariable").to.be.true; diff --git a/ts2panda/tests/statements/functionDeclaration.test.ts b/ts2panda/tests/statements/functionDeclaration.test.ts index 7c5ef3b078..6405c9cd96 100644 --- a/ts2panda/tests/statements/functionDeclaration.test.ts +++ b/ts2panda/tests/statements/functionDeclaration.test.ts @@ -46,9 +46,10 @@ describe("FunctionDeclarationTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("function foo() {}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); + let funcInternalName = "UnitTest.foo"; let funcName = "foo"; let expected = [ - new Definefunc(new Imm(0), funcName, new Imm(0)), + new Definefunc(new Imm(0), funcInternalName, new Imm(0)), new Stglobalvar(new Imm(1), funcName), new Returnundefined() ]; @@ -68,7 +69,7 @@ describe("FunctionDeclarationTest", function () { `); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ - new Definefunc(new Imm(0), "#2#foo", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.#2#foo", new Imm(0)), new Stglobalvar(new Imm(1), "foo"), new Returnundefined() ]; @@ -86,12 +87,12 @@ describe("FunctionDeclarationTest", function () { IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let funcReg = new VReg(); let expected = [ - new Definefunc(new Imm(0), "foo", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.foo", new Imm(0)), new Sta(funcReg), new Returnundefined() ]; - let functionPg = snippetCompiler.getPandaGenByName("out"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.out"); let insns = functionPg!.getInsns(); let functionScope = functionPg!.getScope(); @@ -109,7 +110,7 @@ describe("FunctionDeclarationTest", function () { let insns = snippetCompiler.getGlobalInsns(); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ - new Definefunc(new Imm(0), "foo", new Imm(0)), + new Definefunc(new Imm(0), "UnitTest.foo", new Imm(0)), new Sttoglobalrecord(new Imm(1), "foo"), new Returnundefined() ]; @@ -124,7 +125,7 @@ describe("FunctionDeclarationTest", function () { IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected_main = [ - new Definefunc(new Imm(0), "test", new Imm(1)), + new Definefunc(new Imm(0), "UnitTest.test", new Imm(1)), new Stglobalvar(new Imm(1), "test"), new Returnundefined() ]; @@ -142,10 +143,10 @@ describe("FunctionDeclarationTest", function () { ]; compilerunit.forEach(element => { - if (element.internalName == "func_main_0") { + if (element.internalName == "UnitTest.func_main_0") { let insns = element.getInsns(); expect(checkInstructions(insns, expected_main)).to.be.true; - } else if (element.internalName == "test") { + } else if (element.internalName == "UnitTest.test") { let insns = element.getInsns(); expect(checkInstructions(insns, expected_func)).to.be.true; let parameterLength = element.getParameterLength(); @@ -168,7 +169,7 @@ describe("FunctionDeclarationTest", function () { new Returnundefined(), ]; - let functionPg = snippetCompiler.getPandaGenByName("test"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.test"); let insns = functionPg!.getInsns(); expect(checkInstructions(insns, expected_func)).to.be.true; diff --git a/ts2panda/tests/statements/variableDeclaration.test.ts b/ts2panda/tests/statements/variableDeclaration.test.ts index 95d5bbb47a..88db2c51f3 100644 --- a/ts2panda/tests/statements/variableDeclaration.test.ts +++ b/ts2panda/tests/statements/variableDeclaration.test.ts @@ -165,7 +165,7 @@ describe("VariableDeclarationTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("function a() {var i;}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); - let funcPg = snippetCompiler.getPandaGenByName("a"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let functionScope = funcPg!.getScope(); let insns = funcPg!.getInsns(); let expected = [ @@ -184,7 +184,7 @@ describe("VariableDeclarationTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("function a() {let i;}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); - let funcPg = snippetCompiler.getPandaGenByName("a"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let functionScope = funcPg!.getScope(); let insns = funcPg!.getInsns(); let expected = [ @@ -201,7 +201,7 @@ describe("VariableDeclarationTest", function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("function a() {const i = 5;}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); - let funcPg = snippetCompiler.getPandaGenByName("a"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.a"); let functionScope = funcPg!.getScope(); let insns = funcPg!.getInsns(); let expected = [ @@ -217,7 +217,7 @@ describe("VariableDeclarationTest", function () { it('let i in a local scope', function () { let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile("{let i;}"); - let funcPg = snippetCompiler.getPandaGenByName("func_main_0"); + let funcPg = snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let localScope = funcPg!.getScope(); let insns = funcPg!.getInsns(); diff --git a/ts2panda/tests/types/array.test.ts b/ts2panda/tests/types/array.test.ts index 131bcc2e47..48f8b2db92 100644 --- a/ts2panda/tests/types/array.test.ts +++ b/ts2panda/tests/types/array.test.ts @@ -30,7 +30,7 @@ describe("array tests in array.test.ts", function() { it("test array with primitives", function() { let fileNames = 'tests/types/array/array_primitives.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -75,7 +75,7 @@ describe("array tests in array.test.ts", function() { it("test array with class", function() { let fileNames = 'tests/types/array/array_class.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -108,7 +108,7 @@ describe("array tests in array.test.ts", function() { it("test array with multi same primitive", function() { let fileNames = 'tests/types/array/array_multi_same_primi.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -159,7 +159,7 @@ describe("array tests in array.test.ts", function() { it("test array with multi same class", function() { let fileNames = 'tests/types/array/array_multi_same_class.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -193,7 +193,7 @@ describe("array tests in array.test.ts", function() { it("test array with union", function() { let fileNames = 'tests/types/array/array_union.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -222,7 +222,7 @@ describe("array tests in array.test.ts", function() { it("test array with object", function() { let fileNames = 'tests/types/array/array_object.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/types/class.test.ts b/ts2panda/tests/types/class.test.ts index 1a58c70fb9..00247f961d 100644 --- a/ts2panda/tests/types/class.test.ts +++ b/ts2panda/tests/types/class.test.ts @@ -30,7 +30,7 @@ describe("class tests in class.test.ts", function () { it("test class with no parameter in block", function () { let fileNames = 'tests/types/class/class_constr_no_para.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -67,7 +67,7 @@ describe("class tests in class.test.ts", function () { it("test class with parameter in block", function () { let fileNames = 'tests/types/class/class_constr_para.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -103,7 +103,7 @@ describe("class tests in class.test.ts", function () { it("test class fields type", function () { let fileNames = 'tests/types/class/class_fields.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -138,7 +138,7 @@ describe("class tests in class.test.ts", function () { it("test class methods type", function () { let fileNames = 'tests/types/class/class_methods.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -180,7 +180,7 @@ describe("class tests in class.test.ts", function () { it("test class static fields type", function () { let fileNames = 'tests/types/class/class_static_fields.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -215,7 +215,7 @@ describe("class tests in class.test.ts", function () { it("test class static methods type", function () { let fileNames = 'tests/types/class/class_static_methods.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -258,7 +258,7 @@ describe("class tests in class.test.ts", function () { it("test abstract class type", function () { let fileNames = 'tests/types/class/class_abstract.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -303,7 +303,7 @@ describe("class tests in class.test.ts", function () { it("test class implements type", function () { let fileNames = 'tests/types/class/class_implements.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/types/function.test.ts b/ts2panda/tests/types/function.test.ts index 5a37e3d989..3003d42926 100644 --- a/ts2panda/tests/types/function.test.ts +++ b/ts2panda/tests/types/function.test.ts @@ -30,7 +30,7 @@ describe("function tests in function.test.ts", function () { it("test function with no parameter", function () { let fileNames = 'tests/types/function/function_no_para.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -60,7 +60,7 @@ describe("function tests in function.test.ts", function () { it("test function with muti parameter", function () { let fileNames = 'tests/types/function/function_multi_para.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -92,7 +92,7 @@ describe("function tests in function.test.ts", function () { it("test function with same type of paras and return", function () { let fileNames = 'tests/types/function/function_same_para_and_return.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -131,7 +131,7 @@ describe("function tests in function.test.ts", function () { it("test function with class as parameter", function () { let fileNames = 'tests/types/function/function_class_para.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -172,7 +172,7 @@ describe("function tests in function.test.ts", function () { it("test function with class as return", function () { let fileNames = 'tests/types/function/function_class_return.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/types/object.test.ts b/ts2panda/tests/types/object.test.ts index 9f7446a20a..bfaeef5ae8 100644 --- a/ts2panda/tests/types/object.test.ts +++ b/ts2panda/tests/types/object.test.ts @@ -30,7 +30,7 @@ describe("object tests in object.test.ts", function() { it("test object with primitives", function() { let fileNames = 'tests/types/object/object_primi.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -56,7 +56,7 @@ describe("object tests in object.test.ts", function() { it("test object with user defined type", function() { let fileNames = 'tests/types/object/object_class.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/types/primitives.test.ts b/ts2panda/tests/types/primitives.test.ts index 0f726cd7fc..3603a83536 100644 --- a/ts2panda/tests/types/primitives.test.ts +++ b/ts2panda/tests/types/primitives.test.ts @@ -30,7 +30,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives in block", function() { let fileNames = 'tests/types/primitives/primitives_in_block.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -59,18 +59,18 @@ describe("primitives tests in primitives.test.ts", function() { it("test number in function", function() { let fileNames = 'tests/types/primitives/primitives_in_function.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("numberFunc"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.numberFunc"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ - ["#0#input", 1], - ["#1#num", 1], - ["#2#bool", 2], - ["#3#str", 4], - ["#4#sym", 5], - ["#5#nu", 6], - ["#6#und", 7], - ["#7#vd", 3], + ["#3#input", 1], + ["#4#num", 1], + ["#5#bool", 2], + ["#6#str", 4], + ["#7#sym", 5], + ["#8#nu", 6], + ["#9#und", 7], + ["#10#vd", 3], ] let vreg2TypeMap = createVRegTypePair(extectedVRegTypePair); expect(compareVReg2Type(vreg2TypeMap, locals), "check vreg typeInfo").to.be.true; @@ -99,7 +99,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives in for", function() { let fileNames = 'tests/types/primitives/primitives_in_for.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -129,7 +129,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives in if", function() { let fileNames = 'tests/types/primitives/primitives_in_if.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -158,7 +158,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives in class", function() { let fileNames = 'tests/types/primitives/primitives_in_class.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -196,7 +196,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives with only type annotations", function() { let fileNames = 'tests/types/primitives/primitives_only_type_annotation.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -224,7 +224,7 @@ describe("primitives tests in primitives.test.ts", function() { it("test primitives without type annotations", function() { let fileNames = 'tests/types/primitives/primitives_no_type_annotation.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/types/union.test.ts b/ts2panda/tests/types/union.test.ts index 299d54a28b..4d97791ae0 100644 --- a/ts2panda/tests/types/union.test.ts +++ b/ts2panda/tests/types/union.test.ts @@ -30,7 +30,7 @@ describe("union tests in union.test.ts", function () { it("test union with primitives", function () { let fileNames = 'tests/types/union/union_primitives.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -68,7 +68,7 @@ describe("union tests in union.test.ts", function () { it("test union with user defined type", function () { let fileNames = 'tests/types/union/union_userDefinedType.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -104,7 +104,7 @@ describe("union tests in union.test.ts", function () { it("test union with multi same primitives", function () { let fileNames = 'tests/types/union/union_multi_same_primi.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ @@ -130,7 +130,7 @@ describe("union tests in union.test.ts", function () { it("test union with multi same user defined type", function () { let fileNames = 'tests/types/union/union_multi_userDefinedType.ts'; let result = compileTsWithType(fileNames); - let functionPg = result.snippetCompiler.getPandaGenByName("func_main_0"); + let functionPg = result.snippetCompiler.getPandaGenByName("UnitTest.func_main_0"); let locals = functionPg!.getLocals(); // check vreg let extectedVRegTypePair = [ diff --git a/ts2panda/tests/utils/base.ts b/ts2panda/tests/utils/base.ts index 2d9f7ed318..49c7c5b52d 100644 --- a/ts2panda/tests/utils/base.ts +++ b/ts2panda/tests/utils/base.ts @@ -146,7 +146,7 @@ export function compileAllSnippet(snippet: string, passes?: Pass[], literalBuffe jshelpers.bindSourceFile(sourceFile, {}); CmdOptions.isWatchEvaluateExpressionMode() ? setGlobalStrict(true) : setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions)); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); if (!passes) { passes = []; @@ -166,7 +166,7 @@ export function compileMainSnippet(snippet: string, pandaGen?: PandaGen, scope?: // only return main function if (compileFunc) { compileUnits.filter((pg) => { - return (pg.internalName == "func_main_0"); + return (pg.internalName == "UnitTest.func_main_0"); }) } @@ -191,7 +191,7 @@ export function compileAfterSnippet(snippet: string, name:string, isCommonJs: bo } jshelpers.bindSourceFile(sourceFile, {}); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions)); - let compilerDriver = new CompilerDriver('UnitTest'); + let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); compilerDriver.setCustomPasses([]); compilerDriver.compileUnitTest(sourceFile, []); compileUnits = compilerDriver.getCompilationUnits(); @@ -228,7 +228,7 @@ export class SnippetCompiler { } getGlobalInsns(): IRNode[] { - let root = this.getPandaGenByName("func_main_0"); + let root = this.getPandaGenByName("UnitTest.func_main_0"); if (root) { return root.getInsns(); } else { @@ -237,7 +237,7 @@ export class SnippetCompiler { } getGlobalScope(): Scope | undefined { - let globalPandaGen = this.getPandaGenByName("func_main_0"); + let globalPandaGen = this.getPandaGenByName("UnitTest.func_main_0"); return globalPandaGen ? globalPandaGen.getScope()!.getNearestVariableScope() : undefined; } diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 57c350067e..251750154d 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -58,6 +58,7 @@ constexpr std::size_t BOUND_RIGHT = 0; constexpr std::size_t LINE_NUMBER = 0; constexpr bool IS_DEFINED = true; int g_opCodeIndex = 0; +std::string g_recordName = ""; std::unordered_map g_opcodeMap = { #define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) {g_opCodeIndex++, panda::pandasm::Opcode::opcode}, PANDA_INSTRUCTION_LIST(OPLIST) @@ -69,7 +70,6 @@ std::unordered_map g_opcodeMap = { static panda::pandasm::Record MakeRecordDefinition(const std::string &name) { auto record = panda::pandasm::Record(name, LANG_EXT); - return record; } @@ -879,35 +879,27 @@ static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog) prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord)); } -static void GenerateCommonJsRecord(panda::pandasm::Program &prog, bool isCommonJs) -{ - // when multi-abc file get merged, field should be inserted in abc's own record - auto commonjsRecord = panda::pandasm::Record("_CommonJsRecord", LANG_EXT); - commonjsRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); - auto isCommonJsField = panda::pandasm::Field(LANG_EXT); - isCommonJsField.name = "isCommonJs"; - isCommonJsField.type = panda::pandasm::Type("u8", 0); - isCommonJsField.metadata->SetValue(panda::pandasm::ScalarValue::Create( - static_cast(isCommonJs))); - commonjsRecord.field_list.emplace_back(std::move(isCommonJsField)); - - prog.record_table.emplace(commonjsRecord.name, std::move(commonjsRecord)); -} - -static void GenerateESModuleRecord(panda::pandasm::Program &prog) +static void SetCommonjsField(panda::pandasm::Program &prog, bool isCommonjs) { - auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT); - ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); - prog.record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord)); + auto iter = prog.record_table.find(g_recordName); + if (iter != prog.record_table.end()) { + auto &rec = iter->second; + auto isCommonJsField = panda::pandasm::Field(LANG_EXT); + isCommonJsField.name = "isCommonjs"; + isCommonJsField.type = panda::pandasm::Type("u8", 0); + isCommonJsField.metadata->SetValue( + panda::pandasm::ScalarValue::Create(static_cast(isCommonjs))); + rec.field_list.emplace_back(std::move(isCommonJsField)); + } } static void AddModuleRecord(panda::pandasm::Program &prog, const std::string &moduleName) { - auto iter = prog.record_table.find("_ESModuleRecord"); + auto iter = prog.record_table.find(g_recordName); if (iter != prog.record_table.end()) { auto &rec = iter->second; auto moduleIdxField = panda::pandasm::Field(LANG_EXT); - moduleIdxField.name = moduleName; + moduleIdxField.name = "moduleRecordIdx"; moduleIdxField.type = panda::pandasm::Type("u32", 0); std::string moduleId = GetLiteralId(g_newLiteralArrayIndex); moduleIdxField.metadata->SetValue( @@ -937,23 +929,11 @@ int ParseJson(const std::string &data, Json::Value &rootValue) return RETURN_SUCCESS; } -static void ParseModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) -{ - Logd("----------------parse module_mode-----------------"); - if (rootValue.isMember("module_mode") && rootValue["module_mode"].isBool()) { - if (rootValue["module_mode"].asBool()) { - GenerateESModuleRecord(prog); - } - } -} - -static void ParseCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) +static void SetCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) { Logd("------------parse commonjs_module_mode-------------"); if (rootValue.isMember("commonjs_module") && rootValue["commonjs_module"].isBool()) { - if (rootValue["commonjs_module"].asBool()) { - GenerateCommonJsRecord(prog, true); - } + SetCommonjsField(prog, rootValue["commonjs_module"].asBool()); } } @@ -1037,8 +1017,7 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & { GenerateESCallTypeAnnotationRecord(prog); GenerateESTypeAnnotationRecord(prog); - ParseModuleMode(rootValue, prog); - ParseCommonJsModuleMode(rootValue, prog); + SetCommonJsModuleMode(rootValue, prog); ParseLogEnable(rootValue); ParseDebugMode(rootValue); ParseOptLevel(rootValue); @@ -1055,9 +1034,10 @@ static void ParseSingleFunc(const Json::Value &rootValue, panda::pandasm::Progra prog.function_table.emplace(function.name.c_str(), std::move(function)); } -static void ParseSingleRec(const Json::Value &rootValue, panda::pandasm::Program &prog) +static void ParseRec(const Json::Value &rootValue, panda::pandasm::Program &prog) { auto record = ParseRecord(rootValue["rb"]); + g_recordName = record.name; prog.record_table.emplace(record.name.c_str(), std::move(record)); } @@ -1255,7 +1235,7 @@ static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Progr } case static_cast(JsonType::RECORD): { if (rootValue.isMember("rb") && rootValue["rb"].isObject()) { - ParseSingleRec(rootValue, prog); + ParseRec(rootValue, prog); } break; } diff --git a/ts2panda/ts2abc/ts2abc_options.h b/ts2panda/ts2abc/ts2abc_options.h index 76f326fe25..03d56e78e9 100755 --- a/ts2panda/ts2abc/ts2abc_options.h +++ b/ts2panda/ts2abc/ts2abc_options.h @@ -224,7 +224,7 @@ namespace panda::ts2abc { panda::PandArg compile_by_pipe_arg_{ "compile-by-pipe", false, R"(Compile a json file that is passed by pipe)"}; panda::PandArg compiler_output_proto_{ "output-proto", "", - R"(compiler proto serialize binary output (.proto))"}; + R"(Specify the output name for serializd protobuf file (.protoBin))"}; panda::PandArg Tail_Arg1_arg_{ "ARG_1", "", R"(Path to input(json file) or path to output(ark bytecode)" " when 'compile-by-pipe' enabled)"}; -- Gitee From 47f77d8c9f97764d8fbd21fbbd078009d1431b62 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Thu, 20 Oct 2022 14:38:22 +0800 Subject: [PATCH 08/59] Remove call type optimization of ts file Signed-off-by: zhangrengao Change-Id: Ic8f8af8eacdcfc275e6f6565131fdbd2fd0c1835 --- ts2panda/src/compiler.ts | 67 ------------------ ts2panda/src/compilerDriver.ts | 1 + ts2panda/src/expression/metaProperty.ts | 2 - ts2panda/src/lexenv.ts | 6 -- ts2panda/src/scope.ts | 21 ------ ts2panda/src/statement/classStatement.ts | 6 -- ts2panda/ts2abc/ts2abc.cpp | 86 +++++++++--------------- 7 files changed, 33 insertions(+), 156 deletions(-) diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index d15844a000..a4027cacb9 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -164,7 +164,6 @@ export class Compiler { this.compileSourceFileOrBlock(this.rootNode); } else { this.compileFunctionLikeDeclaration(this.rootNode); - this.callOpt(); } } @@ -180,57 +179,6 @@ export class Compiler { return this.envUnion[this.envUnion.length - 1]; } - private callOpt() { - if (CmdOptions.isDebugMode()) { - return; - } - let CallMap: Map = new Map([ - ["this", 1], - ["4newTarget", 2], - ["0newTarget", 2], - ["argumentsOrRestargs", 4], - ["4funcObj", 8] - ]); - let callType = 0; - let scope = this.pandaGen.getScope(); - - if (scope instanceof FunctionScope) { - let tempLocals: VReg[] = []; - let tempNames: Set = new Set(); - let count = 0; - // 4funcObj/newTarget/this - for (let i = 0; i < 3; i++) { - if (scope.getCallOpt().has(scope.getParameters()[i].getName())) { - tempLocals.push(this.pandaGen.getLocals()[i]); - callType += CallMap.get(scope.getParameters()[i].getName()) ?? 0; - } else { - tempNames.add(scope.getParameters()[i].getName()); - count++; - } - } - // actual parameters - for (let i = 3; i < this.pandaGen.getLocals().length; i++) { - tempLocals.push(this.pandaGen.getLocals()[i]); - } - let name2variable = scope.getName2variable(); - // @ts-ignore - name2variable.forEach((value, key) => { - if (tempNames.has(key)) { - name2variable.delete(key) - } - }) - - this.pandaGen.setLocals(tempLocals); - this.pandaGen.setParametersCount(this.pandaGen.getParametersCount() - count); - - if (scope.getArgumentsOrRestargs()) { - callType += CallMap.get("argumentsOrRestargs") ?? 0; - } - - this.pandaGen.setCallType(callType); - } - } - private storeFuncObj2LexEnvIfNeeded() { let rootNode = this.rootNode; if (!ts.isFunctionExpression(rootNode) && !ts.isMethodDeclaration(rootNode)) { @@ -288,9 +236,6 @@ export class Compiler { pandaGen.getVregForVariable(variableInfo.v)); } else { if (v && v.isLexVar) { - if ((arg === "this" || arg === "4newTarget") && variableInfo.scope instanceof FunctionScope) { - variableInfo.scope.setCallOpt(arg); - } if (arg === "arguments" && variableInfo.scope instanceof FunctionScope) { variableInfo.scope.setArgumentsOrRestargs(); } @@ -1062,8 +1007,6 @@ export class Compiler { let { scope, level, v } = this.scope.find("this"); - this.setCallOpt(scope, "this") - if (!v) { throw new Error("\"this\" not found"); } @@ -1467,8 +1410,6 @@ export class Compiler { let level = thisInfo.level; let v = thisInfo.v; - this.setCallOpt(scope, "this") - if (scope && level >= 0) { let needSetLexVar: boolean = false; while (curScope != scope) { @@ -1497,8 +1438,6 @@ export class Compiler { let pandaGen = this.pandaGen; let thisInfo = this.getCurrentScope().find("this"); - this.setCallOpt(thisInfo.scope, "this") - if (thisInfo.v!.isLexVar) { let slot = (thisInfo.v).idxLex; let value = pandaGen.getTemp(); @@ -1510,12 +1449,6 @@ export class Compiler { } } - setCallOpt(scope: Scope | undefined, callOptStr: String) { - if (scope instanceof FunctionScope) { - scope.setCallOpt(callOptStr); - } - } - getPandaGen() { return this.pandaGen; } diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index 2897861533..ce216975fb 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -186,6 +186,7 @@ export class CompilerDriver { listenErrorEvent(ts2abcProc); try { + // must keep [dumpRecord] at first Ts2Panda.dumpRecord(ts2abcProc, this.recordName); Ts2Panda.dumpCmdOptions(ts2abcProc); Ts2Panda.dumpRecordName(ts2abcProc, getRecordName(CompilerDriver.srcNode)); diff --git a/ts2panda/src/expression/metaProperty.ts b/ts2panda/src/expression/metaProperty.ts index eadef5cdee..de0500b305 100644 --- a/ts2panda/src/expression/metaProperty.ts +++ b/ts2panda/src/expression/metaProperty.ts @@ -23,8 +23,6 @@ export function compileMetaProperty(expr: ts.MetaProperty, compiler: Compiler) { if (id == "target") { let { scope, level, v } = curScope.find("4newTarget"); - compiler.setCallOpt(scope, "4newTarget"); - if (!v) { throw new Error("fail to access new.target"); } else { diff --git a/ts2panda/src/lexenv.ts b/ts2panda/src/lexenv.ts index ee896e07f6..aba261946a 100644 --- a/ts2panda/src/lexenv.ts +++ b/ts2panda/src/lexenv.ts @@ -91,9 +91,6 @@ export class VariableAccessLoad extends VariableAccessBase { pandaGen.freeTemps(holeReg); return insns; } - if (v.getName() === "4funcObj") { - this.scope.setCallOpt("4funcObj") - } insns.push(loadAccumulator(bindVreg)); return insns; @@ -160,9 +157,6 @@ export class VariableAcessStore extends VariableAccessBase { checkConstAssignment(pandaGen, v, insns, this.node); } - if (v.getName() === "4funcObj") { - this.scope.setCallOpt("4funcObj") - } insns.push(storeAccumulator(bindVreg)); return insns; diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index 3c8b01a1c5..637dc19b6c 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -94,7 +94,6 @@ export abstract class Scope { // for debuginfo protected startInsIdx: number | undefined; protected endInsIdx: number | undefined; - private callOpt: Set = new Set(); private isArgumentsOrRestargs: boolean = false; constructor() { } @@ -259,26 +258,6 @@ export abstract class Scope { return this.decls; } - public getCallOpt() { - return this.callOpt; - } - - public setCallOpt(key: String) { - if (this instanceof FunctionScope) { - this.callOpt.add(key); - } else { - let parent = this.parent; - while (parent != undefined) { - if (parent instanceof FunctionScope) { - parent.callOpt.add(key); - break; - } else { - parent = parent.parent; - } - } - } - } - public setArgumentsOrRestargs() { this.isArgumentsOrRestargs = true; } diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 56a29cbcae..3b4368dbcf 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -364,9 +364,6 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar let curScope = compiler.getCurrentScope(); let { scope, level, v } = curScope.find("this"); - compiler.setCallOpt(scope, "this"); - compiler.setCallOpt(scope, "4newTarget"); - if (scope && level >= 0) { let tmpScope = curScope; let needSetLexVar: boolean = false; @@ -381,9 +378,6 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar if (needSetLexVar) { scope.setLexVar(v, curScope); } - if (needSetLexVar && curScope instanceof FunctionScope) { - curScope.setCallOpt("0newTarget"); - } } if (hasSpread) { diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 251750154d..1cba8c9cb7 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -177,6 +177,11 @@ static std::string GetLiteralId(int64_t index) return g_recordName + "_" + std::to_string(index); } +static bool IsFuncMain0(std::string funcName) { + std::string expectedName = g_recordName + ".func_main_0"; + return funcName == expectedName; +} + static std::string ParseUnicodeEscapeString(const std::string &data) { const int unicodeEscapeSymbolLen = 2; @@ -591,34 +596,6 @@ static void ParseFunctionCatchTables(const Json::Value &function, panda::pandasm } } -static void ParseFunctionCallType(const Json::Value &function, panda::pandasm::Function &pandaFunc) -{ - if (g_debugModeEnabled) { - return; - } - - std::string funcName = ""; - if (function.isMember("n") && function["n"].isString()) { - funcName = function["n"].asString(); - } - if (funcName == "func_main_0") { - return; - } - - uint32_t callType = 0; - if (function.isMember("ct") && function["ct"].isInt()) { - callType = function["ct"].asUInt(); - } - panda::pandasm::AnnotationData callTypeAnnotation("_ESCallTypeAnnotation"); - std::string annotationName = "callType"; - panda::pandasm::AnnotationElement callTypeAnnotationElement( - annotationName, std::make_unique( - panda::pandasm::ScalarValue::Create(callType))); - callTypeAnnotation.AddElement(std::move(callTypeAnnotationElement)); - const_cast&>( - pandaFunc.metadata->GetAnnotations()).push_back(std::move(callTypeAnnotation)); -} - static std::vector> GetInstTypeMap(const Json::Value &function, panda::pandasm::Function &pandaFunc) { @@ -778,7 +755,7 @@ static void ParseFunctionExportedType(const Json::Value &function, panda::pandas std::string funcName = ""; if (function.isMember("n") && function["n"].isString()) { funcName = function["n"].asString(); - if (funcName != "func_main_0") { + if (!IsFuncMain0(funcName)) { return; } } @@ -805,7 +782,7 @@ static void ParseFunctionDeclaredType(const Json::Value &function, panda::pandas std::string funcName = ""; if (function.isMember("n") && function["n"].isString()) { funcName = function["n"].asString(); - if (funcName != "func_main_0") { + if (!IsFuncMain0(funcName)) { return; } } @@ -857,7 +834,7 @@ static panda::pandasm::Function ParseFunction(const Json::Value &function, panda ParseFunctionKind(function, pandaFunc); ParseFunctionIcSize(function, pandaFunc); - if (g_isDtsFile && pandaFunc.name != "func_main_0") { + if (g_isDtsFile && !IsFuncMain0(pandaFunc.name)) { pandaFunc.metadata->SetAttribute("external"); } @@ -1190,29 +1167,30 @@ static void ParseSingleModule(const Json::Value &rootValue, panda::pandasm::Prog static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Program &prog) { - auto typeInfoRecord = rootValue["ti"]; - auto typeFlag = typeInfoRecord["tf"].asBool(); - auto typeSummaryIndex = typeInfoRecord["tsi"].asString(); - auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT); - ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); - - auto typeFlagField = panda::pandasm::Field(LANG_EXT); - typeFlagField.name = "typeFlag"; - typeFlagField.type = panda::pandasm::Type("u8", 0); - typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( - static_cast(typeFlag))); - ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField)); - - if (g_enableTypeinfo) { - auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); - typeSummaryIndexField.name = "typeSummaryOffset"; - typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); - typeSummaryIndexField.metadata->SetValue( - panda::pandasm::ScalarValue::Create(typeSummaryIndex)); - ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField)); - } - - prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord)); + auto iter = prog.record_table.find(g_recordName); + if (iter != prog.record_table.end()) { + auto &rec = iter->second; + + auto typeInfoRecord = rootValue["ti"]; + auto typeFlag = typeInfoRecord["tf"].asBool(); + auto typeSummaryIndex = typeInfoRecord["tsi"].asUInt(); + + auto typeFlagField = panda::pandasm::Field(LANG_EXT); + typeFlagField.name = "typeFlag"; + typeFlagField.type = panda::pandasm::Type("u8", 0); + typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(typeFlag))); + rec.field_list.emplace_back(std::move(typeFlagField)); + + if (g_enableTypeinfo) { + auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); + typeSummaryIndexField.name = "typeSummaryOffset"; + typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); + typeSummaryIndexField.metadata->SetValue( + panda::pandasm::ScalarValue::Create(typeSummaryIndex)); + rec.field_list.emplace_back(std::move(typeSummaryIndexField)); + } + } } static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Program &prog) -- Gitee From 5d3e341926443ac709c4ec5b7d5e5014995b64ef Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Mon, 26 Sep 2022 10:22:31 +0800 Subject: [PATCH 09/59] Support ts2abc && es2abc && aot test262 cases in merged style Signed-off-by: gavin1012_hw Change-Id: I4e750e9ad20d9a0ea10c585176e3fe6145449f39 --- merge_abc/src/options.h | 2 +- test262/run_sunspider.py | 96 +++++++++++++------ ts2panda/src/base/bcGenUtil.ts | 9 +- ts2panda/src/base/lexEnv.ts | 6 +- ts2panda/src/base/util.ts | 24 ++++- ts2panda/src/cmdOptions.ts | 15 ++- ts2panda/src/compilerDriver.ts | 1 - ts2panda/src/index.ts | 43 +++------ ts2panda/src/pandagen.ts | 15 ++- ts2panda/src/pandasm.ts | 2 - ts2panda/src/ts2panda.ts | 14 --- ts2panda/tests/esmodule.test.ts | 3 +- ts2panda/tests/expression/call.test.ts | 4 +- ts2panda/tests/expression/commalist.test.ts | 4 +- ts2panda/tests/expression/literal.test.ts | 27 ++++-- ts2panda/tests/statements/switch.test.ts | 2 +- ts2panda/tests/types/array.test.ts | 24 ++--- ts2panda/tests/types/class.test.ts | 52 +++++----- ts2panda/tests/types/function.test.ts | 18 ++-- ts2panda/tests/types/object.test.ts | 8 +- ts2panda/tests/types/primitives.test.ts | 6 +- ts2panda/tests/types/union.test.ts | 16 ++-- ts2panda/tests/utils/base.ts | 2 + .../tests/watch_expression/addWatch.test.ts | 6 +- ts2panda/ts2abc/main.cpp | 32 +++++++ ts2panda/ts2abc/ts2abc.cpp | 70 ++++++++++++-- ts2panda/ts2abc/ts2abc.h | 1 + ts2panda/ts2abc/ts2abc_options.h | 44 ++++++++- 28 files changed, 359 insertions(+), 187 deletions(-) diff --git a/merge_abc/src/options.h b/merge_abc/src/options.h index e1c76e1702..8475ab1d20 100644 --- a/merge_abc/src/options.h +++ b/merge_abc/src/options.h @@ -58,7 +58,7 @@ public: private: panda::PandArgParser *argparser_; std::string errorMsg_; - std::string protoBinSuffix_ {"bin"}; + std::string protoBinSuffix_ {"protoBin"}; std::string protoPathInput_; std::string outputFileName_ {"modules.abc"}; std::string outputFilePath_; diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 30dbaca4bd..cc3b9bd3b4 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -97,6 +97,7 @@ ARK_AOT_TOOL = DEFAULT_ARK_AOT_TOOL ARK_FRONTEND = DEFAULT_ARK_FRONTEND ARK_FRONTEND_BINARY = DEFAULT_ARK_FRONTEND_BINARY ARK_ARCH = DEFAULT_ARK_ARCH +PROTO_BIN_SUFFIX = "protoBin" def output(retcode, msg): @@ -230,77 +231,114 @@ class ArkProgram(): output_file = os.path.splitext(os.path.join(BASE_OUT_DIR, os.path.split(dependency)[1]))[0] output_abc = f"{output_file}.abc" - proto_bin_file = f"{output_file}.bin" - output_abc_name = os.path.basename(output_abc) - frontend_tool = self.ark_frontend_binary merge_abc_binary = self.args.merge_abc_binary merge_abc_mode = self.merge_abc_mode if merge_abc_mode != "0": + proto_bin_file = output_file + "." + PROTO_BIN_SUFFIX cmd_args = [frontend_tool, dependency, '--outputProto', proto_bin_file, '--module', '--merge-abc'] - proc = subprocess.call(cmd_args) - cmd_args = [merge_abc_binary, '--input', proto_bin_file, '--suffix', - "bin", '--outputFilePath', BASE_OUT_DIR, '--output', - output_abc_name] else: cmd_args = [frontend_tool, dependency, '--output', output_abc, '--module', '--merge-abc'] proc = subprocess.Popen(cmd_args) proc.wait() + def gen_merged_abc(self, dependencies, file_name_pre, proto_bin_file, retcode): + merge_abc_binary = self.args.merge_abc_binary + file_dir = os.path.split(self.js_file)[0] + proto_abc_file = ".".join([os.path.splitext(os.path.basename(self.js_file))[0], "abc"]) + generate_merged_abc = True + # collect protoBin file into new-made testcase dir + if (len(dependencies) != 0): + if os.path.exists(file_name_pre): + subprocess.run(['rm', '-rf', file_name_pre]) + subprocess.run(['mkdir', file_name_pre]) + + for dependency in list(set(dependencies)): + dependency_file_prefix = os.path.basename(dependency)[:-3] + dependency_bin_file = file_dir + "/" + \ + ".".join([dependency_file_prefix, + PROTO_BIN_SUFFIX]) + # test262 report syntax error cases + if not os.path.exists(dependency_bin_file): + generate_merged_abc = False + else: + subprocess.run(['cp', dependency_bin_file, file_name_pre]) + + if not os.path.exists(proto_bin_file): + generate_merged_abc = False + else: + subprocess.run(['cp', proto_bin_file, file_name_pre]) + + if (len(dependencies) != 0) and generate_merged_abc: + # module test262 cases + cmd_args = [merge_abc_binary, '--input', file_name_pre, + '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath', + file_dir, '--output', proto_abc_file] + self.abc_file = f'{file_name_pre}.abc' + retcode = exec_command(cmd_args) + elif os.path.exists(proto_bin_file): + cmd_args = [merge_abc_binary, '--input', proto_bin_file, + '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath', + file_dir, '--output', proto_abc_file] + self.abc_file = f'{file_name_pre}.abc' + retcode = exec_command(cmd_args) + return retcode + def gen_abc(self): js_file = self.js_file file_name_pre = os.path.splitext(js_file)[0] file_name = os.path.basename(js_file) - file_dir = os.path.split(js_file)[0] out_file = f"{file_name_pre}.abc" - proto_bin_file = f"{file_name_pre}.bin" - proto_abc_file = ".".join([os.path.splitext(file_name)[0], "abc"]) + proto_bin_file = file_name_pre + "." + PROTO_BIN_SUFFIX self.abc_file = out_file mod_opt_index = 0 cmd_args = [] + dependency_cmd_args= [] frontend_tool = self.ark_frontend_binary - merge_abc_binary = self.args.merge_abc_binary merge_abc_mode = self.merge_abc_mode + dependencies = [] # pre-generate the dependencies' abc when ark_frontend is [es2panda] - if (file_name in self.module_list or file_name in self.dynamicImport_list) and \ - self.ark_frontend == ARK_FRONTEND_LIST[1]: + if (file_name in self.module_list or file_name in self.dynamicImport_list): search_dir = "language/module-code" if file_name in self.module_list \ else "language/expressions/dynamic-import" dependencies = collect_module_dependencies(js_file, os.path.join(TEST_FULL_DIR, search_dir), []) - for dependency in list(set(dependencies)): - self.gen_dependency_abc(dependency) + if (self.ark_frontend == ARK_FRONTEND_LIST[1]): + for dependency in list(set(dependencies)): + self.gen_dependency_abc(dependency) if self.ark_frontend == ARK_FRONTEND_LIST[0]: mod_opt_index = 3 if merge_abc_mode != "0": - # '--opt-level=0' is added due to failure in optimizer, should be removed later cmd_args = ['node', '--expose-gc', frontend_tool, js_file, - '--output-proto', proto_bin_file, '--opt-level=0'] + '--output-proto', '--merge-abc'] else: cmd_args = ['node', '--expose-gc', frontend_tool, - js_file, '-o', out_file] + js_file, '-o', out_file, '--merge-abc'] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "-m") self.module = True elif self.ark_frontend == ARK_FRONTEND_LIST[1]: mod_opt_index = 1 if merge_abc_mode != "0": - cmd_args = [frontend_tool, '--outputProto', + # '--merge-abc' is added due to 'merge-abc' is not opened as default in es2abc, should be removed later + cmd_args = [frontend_tool, '--function-threads=' + + str(self.es2abc_thread_count), '--outputProto', proto_bin_file, js_file, '--merge-abc'] else: + # '--merge-abc' should be removed when record-name is set as default in es2panda cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), '--function-threads=' + str(self.es2abc_thread_count), '--output', - out_file, js_file] + out_file, js_file, '--merge-abc'] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "--module") self.module = True # get abc file list from import statement - if self.ark_aot and self.module: + if merge_abc_mode == "0" and self.ark_aot and self.module: self.abc_file = os.path.abspath(out_file) js_dir = os.path.dirname(js_file) for line in fileinput.input(js_file): @@ -312,15 +350,14 @@ class ArkProgram(): abc_file = os.path.abspath(f'{js_dir}/{abc_file}') if self.abc_file.find(abc_file) < 0: self.abc_file += f':{abc_file}' + + retcode = exec_command(cmd_args) self.abc_cmd = cmd_args + if merge_abc_mode != "0": - proc = subprocess.call(cmd_args) - cmd_args = [merge_abc_binary, '--input', proto_bin_file, - '--suffix', "bin", '--outputFilePath', - file_dir, '--output', proto_abc_file] - retcode = exec_command(cmd_args) - else: - retcode = exec_command(cmd_args) + retcode = self.gen_merged_abc(dependencies, file_name_pre, + proto_bin_file, retcode) + return retcode def compile_aot(self): @@ -356,7 +393,6 @@ class ArkProgram(): qemu_arg2 = self.arch_root cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool, ICU_PATH, - '--asm-interpreter=1', f'--aot-file={file_name_pre}', f'{file_name_pre}.abc'] elif self.arch == ARK_ARCH_LIST[2]: @@ -365,12 +401,10 @@ class ArkProgram(): qemu_arg2 = self.arch_root cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool, ICU_PATH, - '--asm-interpreter=1', f'--aot-file={file_name_pre}', f'{file_name_pre}.abc'] elif self.arch == ARK_ARCH_LIST[0]: cmd_args = [self.ark_tool, ICU_PATH, - '--asm-interpreter=1', f'--aot-file={file_name_pre}', f'{file_name_pre}.abc'] diff --git a/ts2panda/src/base/bcGenUtil.ts b/ts2panda/src/base/bcGenUtil.ts index 4be0a9afa6..7f87a6533d 100644 --- a/ts2panda/src/base/bcGenUtil.ts +++ b/ts2panda/src/base/bcGenUtil.ts @@ -177,14 +177,13 @@ export function throwDeleteSuperProperty() { return new ThrowDeletesuperproperty(); } -export function newLexicalEnv(numVars: number, scopeInfoIdx: number | undefined) { - if (scopeInfoIdx == undefined) { +export function newLexicalEnv(numVars: number, scopeInfoId: string | undefined) { + if (scopeInfoId == undefined) { return numVars <= MAX_INT8 ? new Newlexenv(new Imm(numVars)) : new WideNewlexenv(new Imm(numVars)); } - let litId: string = scopeInfoIdx.toString() - return numVars <= MAX_INT8 ? new Newlexenvwithname(new Imm(numVars), litId) : - new WideNewlexenvwithname(new Imm(numVars), litId); + return numVars <= MAX_INT8 ? new Newlexenvwithname(new Imm(numVars), scopeInfoId) : + new WideNewlexenvwithname(new Imm(numVars), scopeInfoId); } export function popLexicalEnv() { diff --git a/ts2panda/src/base/lexEnv.ts b/ts2panda/src/base/lexEnv.ts index a6e91703c4..5393dbd8b1 100644 --- a/ts2panda/src/base/lexEnv.ts +++ b/ts2panda/src/base/lexEnv.ts @@ -28,14 +28,14 @@ import { CacheList, getVregisterCache } from "./vregisterCache"; function createLexEnv(pandaGen: PandaGen, scope: VariableScope): IRNode[] { let lexEnvVars = scope.getNumLexEnv(); let insns: IRNode[] = []; - let scopeInfoIdx: number | undefined = undefined; + let scopeInfoId: string | undefined = undefined; let lexVarInfo = scope.getLexVarInfo(); if (CmdOptions.isDebugMode()) { - scopeInfoIdx = pandaGen.appendScopeInfo(lexVarInfo); + scopeInfoId = pandaGen.appendScopeInfo(lexVarInfo); } insns.push( - newLexicalEnv(lexEnvVars, scopeInfoIdx), + newLexicalEnv(lexEnvVars, scopeInfoId), storeAccumulator(getVregisterCache(pandaGen, CacheList.LexEnv)) ); diff --git a/ts2panda/src/base/util.ts b/ts2panda/src/base/util.ts index 9b60cb6d45..25bf68deee 100644 --- a/ts2panda/src/base/util.ts +++ b/ts2panda/src/base/util.ts @@ -392,8 +392,30 @@ export function hasAbstractModifier(node: ts.Node): boolean { export const MAX_INT8 = 127; export const MAX_INT16 = 32767; +export 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; +} + export function getRecordName(node: ts.SourceFile): string { - return ""; // need to be fixed later + let recordName = CmdOptions.getRecordName(); + + if (recordName == "") { + let outputBinName = getOutputBinName(node); + recordName = path.basename(outputBinName, path.extname(outputBinName)); + } + + return recordName; } export function getLiteralKey(node: ts.SourceFile, idx:number): string { diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 94b151eaff..b746fdf986 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -52,7 +52,8 @@ const ts2pandaOptions = [ { name: 'source-file', type: String, defaultValue: "", description: "specify the file path info recorded in generated abc" }, { name: 'generate-tmp-file', type: Boolean, defaultValue: false, description: "whether to generate intermediate temporary files"}, { name: 'record-name', type: String, defaultValue: "", description: "specify the record name." }, - { name: 'output-proto', type: String, defaultValue: "", description: "specify the output name for serializd protobuf file (.protoBin)" }, + { name: 'output-proto', type: Boolean, defaultValue: false, description: "Output protoBin file. Default: false" }, + { name: 'proto-name', type: String, defaultValue: "", description: "specify the output name for serializd protobuf file (.protoBin)" }, ] @@ -324,10 +325,20 @@ export class CmdOptions { return this.options["generate-tmp-file"]; } - static getOutputproto(): string { + static isOutputproto(): boolean { + if (!this.options) { + return false; + } return this.options["output-proto"]; } + static getProtoName(): string { + if (!this.options) { + return ""; + } + return this.options["proto-name"]; + } + // @ts-ignore static parseUserCmd(args: string[]): ts.ParsedCommandLine | undefined { this.options = commandLineArgs(ts2pandaOptions, { partial: true }); diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index ce216975fb..00164490d6 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -189,7 +189,6 @@ export class CompilerDriver { // must keep [dumpRecord] at first Ts2Panda.dumpRecord(ts2abcProc, this.recordName); Ts2Panda.dumpCmdOptions(ts2abcProc); - Ts2Panda.dumpRecordName(ts2abcProc, getRecordName(CompilerDriver.srcNode)); for (let i = 0; i < this.pendingCompilationUnits.length; i++) { let unit: PendingCompilationUnit = this.pendingCompilationUnits[i]; diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 26eb031a6d..61f2dbfed0 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -21,10 +21,19 @@ import { CompilerDriver } from "./compilerDriver"; import * as diag from "./diagnostic"; import * as jshelpers from "./jshelpers"; import { LOGE } from "./log"; -import { setGlobalDeclare, setGlobalStrict } from "./strictMode"; +import { + setGlobalDeclare, + setGlobalStrict +} from "./strictMode"; import { TypeChecker } from "./typeChecker"; -import { setPos, isBase64Str, transformCommonjsModule } from "./base/util"; -import { IGNORE_ERROR_CODE } from './ignoreSyntaxError' +import { IGNORE_ERROR_CODE } from './ignoreSyntaxError'; +import { + setPos, + isBase64Str, + transformCommonjsModule, + getRecordName, + getOutputBinName +} from "./base/util"; function checkIsGlobalDeclaration(sourceFile: ts.SourceFile) { for (let statement of sourceFile.statements) { @@ -46,6 +55,7 @@ function checkIsGlobalDeclaration(sourceFile: ts.SourceFile) { function generateDTs(node: ts.SourceFile, options: ts.CompilerOptions) { let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName, getRecordName(node)); + CompilerDriver.srcNode = node; setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); compilerDriver.compile(node); compilerDriver.showStatistics(); @@ -143,21 +153,6 @@ 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; -} - function getDtsFiles(libDir: string): string[] { let dtsFiles:string[] = []; function finDtsFile(dir){ @@ -177,17 +172,6 @@ function getDtsFiles(libDir: string): string[] { return dtsFiles; } -function getRecordName(node: ts.SourceFile): string { - let recordName = CmdOptions.getRecordName(); - - if (recordName == "") { - let outputBinName = getOutputBinName(node); - recordName = path.basename(outputBinName, path.extname(outputBinName)); - } - - return recordName; -} - function specifyCustomLib(customLib) { Compiler.Options.Default["lib"] = customLib; let curFiles = fs.readdirSync(__dirname); @@ -345,6 +329,7 @@ function compileWatchExpression(jsFileName: string, errorMsgFileName: string, op } let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName, watchOutputFileName); + CompilerDriver.srcNode = node; setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); compilerDriver.compile(node); return node; diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 2ffc0c0c2a..b168d00156 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -235,13 +235,12 @@ export class PandaGen { this.setFunctionKind(node); } - public appendScopeInfo(lexVarInfo: Map): number | undefined { + public appendScopeInfo(lexVarInfo: Map): string | undefined { if (lexVarInfo.size == 0) { return undefined; } - let scopeInfoIdx: number | undefined = undefined; - scopeInfoIdx = PandaGen.getLiteralArrayBuffer().length; + let scopeInfoId: string | undefined = undefined; let scopeInfo = new LiteralBuffer(); let scopeInfoLiterals = new Array(); scopeInfoLiterals.push(new Literal(LiteralTag.INTEGER, lexVarInfo.size)); @@ -250,8 +249,8 @@ export class PandaGen { scopeInfoLiterals.push(new Literal(LiteralTag.INTEGER, slot)); }); scopeInfo.addLiterals(...scopeInfoLiterals); - PandaGen.getLiteralArrayBuffer().push(scopeInfo); - return scopeInfoIdx; + scopeInfoId = PandaGen.appendLiteralArrayBuffer(scopeInfo); + return scopeInfoId; } public setFunctionKind(node: ts.SourceFile | ts.FunctionLikeDeclaration) { @@ -534,15 +533,15 @@ export class PandaGen { createLexEnv(node: ts.Node, scope: VariableScope | LoopScope) { let numVars = scope.getNumLexEnv(); - let scopeInfoIdx: number | undefined = undefined; + let scopeInfoId: string | undefined = undefined; let lexVarInfo = scope.getLexVarInfo(); if (CmdOptions.isDebugMode()) { - scopeInfoIdx = this.appendScopeInfo(lexVarInfo); + scopeInfoId = this.appendScopeInfo(lexVarInfo); } this.add( node, - newLexicalEnv(numVars, scopeInfoIdx), + newLexicalEnv(numVars, scopeInfoId), ) } diff --git a/ts2panda/src/pandasm.ts b/ts2panda/src/pandasm.ts index bc12caea96..236085d112 100644 --- a/ts2panda/src/pandasm.ts +++ b/ts2panda/src/pandasm.ts @@ -115,11 +115,9 @@ export class Function { export class Record { public name: string; - public metadata: Metadata; constructor(name: string) { this.name = name; - this.metadata = new Metadata(); } } diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 271a015000..05546247ab 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -212,20 +212,6 @@ export class Ts2Panda { }); } - static dumpRecordName(ts2abc: any, recordName: string) { - let recordNameObject = { - "t": JsonType.record_name, - "rn": recordName - } - - let jsonRecordName = escapeUnicode(JSON.stringify(recordNameObject, null, 2)); - jsonRecordName = "$" + jsonRecordName.replace(dollarSign, '#$') + "$"; - if (CmdOptions.isEnableDebugLog()) { - Ts2Panda.jsonString += jsonRecordName; - } - ts2abc.stdio[3].write(jsonRecordName + '\n'); - } - static dumpCmdOptions(ts2abc: any): void { let enableRecordType: boolean = CmdOptions.needRecordType() && CompilerDriver.isTsFile; let options = { diff --git a/ts2panda/tests/esmodule.test.ts b/ts2panda/tests/esmodule.test.ts index e73c64d565..9c8985d79b 100644 --- a/ts2panda/tests/esmodule.test.ts +++ b/ts2panda/tests/esmodule.test.ts @@ -41,6 +41,7 @@ describe("ExportDeclaration", function () { it("exportClassTest ", function() { CmdOptions.isModules = () => {return true}; + CmdOptions.parseUserCmd([""]); let snippetCompiler = new SnippetCompiler(); snippetCompiler.compile(`class C {}; export {C}`); IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`class C {}; export {C}`), 0, undefined); @@ -49,7 +50,7 @@ describe("ExportDeclaration", function () { let classReg = new VReg(); let expected = [ new Mov(new VReg(), new VReg()), - new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#C", "_0", new Imm(0), new VReg()), + new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#C", "snippet_1", new Imm(0), new VReg()), new Sta(classReg), new Lda(classReg), new Stmodulevar(new Imm(0)), diff --git a/ts2panda/tests/expression/call.test.ts b/ts2panda/tests/expression/call.test.ts index a2b6f7bb1d..6e82a070e0 100644 --- a/ts2panda/tests/expression/call.test.ts +++ b/ts2panda/tests/expression/call.test.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; import 'mocha'; +import { CmdOptions } from '../../src/cmdOptions'; import { Dynamicimport, Callarg0, @@ -102,6 +103,7 @@ describe("CallTest", function () { }); it("spread element call of a global standalone function", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet(` const args = [1, 2]; myFunction(...args); @@ -113,7 +115,7 @@ describe("CallTest", function () { let arrayInstance = new VReg(); let expected = [ - new Createarraywithbuffer(new Imm(0), "_0"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(arrayInstance), new Lda(arrayInstance), new Stconsttoglobalrecord(new Imm(1), 'args'), diff --git a/ts2panda/tests/expression/commalist.test.ts b/ts2panda/tests/expression/commalist.test.ts index 6c00a01211..20b13a70a7 100644 --- a/ts2panda/tests/expression/commalist.test.ts +++ b/ts2panda/tests/expression/commalist.test.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; import 'mocha'; +import { CmdOptions } from '../../src/cmdOptions'; import { Returnundefined, Stglobalvar, @@ -37,6 +38,7 @@ import { PandaGen } from '../../src/pandagen'; describe("CommaListExpression", function () { it("computedPropertyName", function () { + CmdOptions.parseUserCmd([""]); let snippetCompiler = new SnippetCompiler(); snippetCompiler.compileAfter(" \ class Test { \ @@ -72,7 +74,7 @@ describe("CommaListExpression", function () { let insns = snippetCompiler.getGlobalInsns(); let expected = [ new Mov(new VReg(), new VReg()), - new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#Test", "_0", new Imm(0), new VReg()), + new Defineclasswithbuffer(new Imm(0), "UnitTest.#1#Test", "test_1", new Imm(0), new VReg()), new Sta(new VReg()), new Lda(new VReg()), new Sttoglobalrecord(new Imm(1), "Test"), diff --git a/ts2panda/tests/expression/literal.test.ts b/ts2panda/tests/expression/literal.test.ts index 832ba0b657..74ea3b3ffe 100644 --- a/ts2panda/tests/expression/literal.test.ts +++ b/ts2panda/tests/expression/literal.test.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; import 'mocha'; +import { CmdOptions } from '../../src/cmdOptions'; import { DiagnosticCode, DiagnosticError } from '../../src/diagnostic'; import { creatAstFromSnippet } from "../utils/asthelper" import { PandaGen } from '../../src/pandagen'; @@ -91,12 +92,13 @@ describe("LiteralTest", function () { }); it("let arr = [1]", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let arr = [1]"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let arrayInstance = new VReg(); let expected = [ - new Createarraywithbuffer(new Imm(0), "_0"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(arrayInstance), new Lda(arrayInstance), new Sttoglobalrecord(new Imm(1), 'arr'), @@ -120,12 +122,13 @@ describe("LiteralTest", function () { }); it("let arr = [1, 2]", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let arr = [1, 2]"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let arrayInstance = new VReg(); let expected = [ - new Createarraywithbuffer(new Imm(0), "_0"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(arrayInstance), new Lda(arrayInstance), new Sttoglobalrecord(new Imm(1), 'arr'), @@ -154,12 +157,13 @@ describe("LiteralTest", function () { }); it("let arr = [1, , 3]", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let arr = [1,, 3]"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let arrayInstance = new VReg(); let expected = [ - new Createarraywithbuffer(new Imm(0), "_0"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(arrayInstance), new Ldai(new Imm(3)), new Stownbyindex(new Imm(1), arrayInstance, new Imm(2)), @@ -173,6 +177,7 @@ describe("LiteralTest", function () { }); it("let arr = [1, ...arr1, 3]", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet(`let arr1 = [1, 2]; let arr = [1, ...arr1, 3]`); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); @@ -180,12 +185,12 @@ describe("LiteralTest", function () { let arrayInstance = new VReg(); let expected = [ - new Createarraywithbuffer(new Imm(0), "_0"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(arrayInstance), new Lda(arrayInstance), new Sttoglobalrecord(new Imm(1), 'arr1'), - new Createarraywithbuffer(new Imm(2), "_1"), + new Createarraywithbuffer(new Imm(2), "snippet_2"), new Sta(arrayInstance), new Ldai(new Imm(1)), new Sta(elemIdxReg), @@ -220,11 +225,12 @@ describe("LiteralTest", function () { }); it("let obj = {a: 1}", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let obj = {a: 1}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let objInstance = new VReg(); let expected = [ - new Createobjectwithbuffer(new Imm(0), "_0"), + new Createobjectwithbuffer(new Imm(0), "snippet_1"), new Sta(objInstance), new Lda(objInstance), new Sttoglobalrecord(new Imm(1), 'obj'), @@ -234,13 +240,14 @@ describe("LiteralTest", function () { }); it("let obj = {0: 1 + 2}", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let obj = {0: 1 + 2}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let objInstance = new VReg(); let lhs = new VReg(); let expected = [ - new Createobjectwithbuffer(new Imm(0), "_0"), + new Createobjectwithbuffer(new Imm(0), "snippet_1"), new Sta(objInstance), new Ldai(new Imm(1)), new Sta(lhs), @@ -255,12 +262,13 @@ describe("LiteralTest", function () { }); it("let obj = {\"str\": 1}", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let obj = {\"str\": 1}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let objInstance = new VReg(); let expected = [ - new Createobjectwithbuffer(new Imm(0), "_0"), + new Createobjectwithbuffer(new Imm(0), "snippet_1"), new Sta(objInstance), new Lda(objInstance), new Sttoglobalrecord(new Imm(1), 'obj'), @@ -270,13 +278,14 @@ describe("LiteralTest", function () { }); it("let a; let obj = {a}", function () { + CmdOptions.parseUserCmd([""]); let insns = compileMainSnippet("let a; let obj = {a}"); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); ((IRNode.pg)).updateIcSize(1); let objInstance = new VReg(); let expected = [ - new Createobjectwithbuffer(new Imm(0), "_0"), + new Createobjectwithbuffer(new Imm(0), "snippet_1"), new Sta(objInstance), new Tryldglobalbyname(new Imm(1), 'a'), new Stownbyname(new Imm(2), "a", objInstance), diff --git a/ts2panda/tests/statements/switch.test.ts b/ts2panda/tests/statements/switch.test.ts index f09bb9bce2..c50027d688 100644 --- a/ts2panda/tests/statements/switch.test.ts +++ b/ts2panda/tests/statements/switch.test.ts @@ -249,7 +249,7 @@ describe("switchTest", function () { switchEndLabel, new Returnundefined() ]; - let functionPg = snippetCompiler.getPandaGenByName("test"); + let functionPg = snippetCompiler.getPandaGenByName("UnitTest.test"); let insns = functionPg!.getInsns(); expect(checkInstructions(insns, expected)).to.be.true; diff --git a/ts2panda/tests/types/array.test.ts b/ts2panda/tests/types/array.test.ts index 48f8b2db92..f671983ef1 100644 --- a/ts2panda/tests/types/array.test.ts +++ b/ts2panda/tests/types/array.test.ts @@ -47,7 +47,7 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 6], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [24, "_5"], [24, "_6"], [2, 0] + [2, 6], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [24, "snippet_5"], [24, "snippet_6"], [2, 0] ], [ [2, 5], [25, 1] @@ -88,17 +88,17 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 3], [24, "_1"], [24, "_2"], [24, "_3"], [2, 0] + [2, 3], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ], [ - [2, 5], [24, "_2"] + [2, 5], [24, "snippet_2"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -131,7 +131,7 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 6], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [24, "_5"], [24, "_6"], [2, 0] + [2, 6], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [24, "snippet_5"], [24, "snippet_6"], [2, 0] ], [ [2, 5], [25, 1] @@ -173,17 +173,17 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 3], [24, "_1"], [24, "_2"], [24, "_3"], [2, 0] + [2, 3], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ], [ - [2, 5], [24, "_2"] + [2, 5], [24, "snippet_2"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -206,13 +206,13 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 4], [2, 2], [25, 4], [25, 1], ], [ - [2, 5], [24, "_1"] + [2, 5], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -234,14 +234,14 @@ describe("array tests in array.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 6], [2, 2], [5, "element1"], [25, 1], [5, "element2"], [25, 4] ], [ - [2, 5], [24, "_1"] + [2, 5], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); diff --git a/ts2panda/tests/types/class.test.ts b/ts2panda/tests/types/class.test.ts index 00247f961d..0ee5e903a6 100644 --- a/ts2panda/tests/types/class.test.ts +++ b/ts2panda/tests/types/class.test.ts @@ -43,13 +43,13 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 3], [24, "_1"], [24, "_2"], [24, "_3"], [2, 0] + [2, 3], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 1], [5, "num"], [25, 1], [2, 0], [2, 0], [2, 1], [5, "constructor"], - [24, "_2"], [2, 0], [2, 0] + [24, "snippet_2"], [2, 0], [2, 0] ], [ [2, 3], [2, 0], @@ -57,7 +57,7 @@ describe("class tests in class.test.ts", function () { [2, 0], [25, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -80,20 +80,20 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 3], [24, "_1"], [24, "_2"], [24, "_3"], [2, 0] + [2, 3], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 1], [5, "num"], [25, 1], [2, 0], [2, 0], [2, 1], [5, "constructor"], - [24, "_2"], [2, 0], [2, 0] + [24, "snippet_2"], [2, 0], [2, 0] ], [ [2, 3], [2, 0], [5, "constructor"], [2, 0], [2, 1], [25, 1], [25, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -116,7 +116,7 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], @@ -128,7 +128,7 @@ describe("class tests in class.test.ts", function () { [2, 0], [2, 1], [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -151,14 +151,14 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 1], [5, "val"], [25, 1], [2, 0], [2, 0], [2, 2], - [5, "setVal"], [24, "_2"], - [5, "getValStr"], [24, "_3"], + [5, "setVal"], [24, "snippet_2"], + [5, "getValStr"], [24, "snippet_3"], [2, 0], [2, 0], ], [ @@ -170,7 +170,7 @@ describe("class tests in class.test.ts", function () { [2, 0], [2, 0], [25, 4] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -193,7 +193,7 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], @@ -205,7 +205,7 @@ describe("class tests in class.test.ts", function () { [25, 4], [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -229,15 +229,15 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 1], [5, "val"], [25, 1], [2, 0], [2, 0], [2, 1], [5, "setVal"], - [24, "_2"], [2, 1], [5, "str"], + [24, "snippet_2"], [2, 1], [5, "str"], [25, 4], [2, 0], [2, 0], [2, 1], - [5, "getStr"], [24, "_3"] + [5, "getStr"], [24, "snippet_3"] ], [ [2, 3], [2, 0], [5, "setVal"], @@ -248,7 +248,7 @@ describe("class tests in class.test.ts", function () { [2, 0], [2, 0], [25, 4] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -272,11 +272,11 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 5], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [24, "_5"], [2, 0] + [2, 5], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [24, "snippet_5"], [2, 0] ], [ [2, 1], [2, 1], [25, 0], [2, 0], - [2, 0], [2, 1], [5, "eat"], [24, "_2"], + [2, 0], [2, 1], [5, "eat"], [24, "snippet_2"], [2, 0], [2, 0] ], [ @@ -284,16 +284,16 @@ describe("class tests in class.test.ts", function () { [2, 0], [2, 0], [25, 0] ], [ - [2, 1], [2, 0], [24, "_1"], + [2, 1], [2, 0], [24, "snippet_1"], [2, 0], [2, 0], [2, 1], [5, "constructor"], - [24, "_4"], [2, 0], [2, 0] + [24, "snippet_4"], [2, 0], [2, 0] ], [ [2, 3], [2, 0], [5, "constructor"], [2, 0], [2, 0], [25, 0] ], [ - [2, 2], [24, "_3"] + [2, 2], [24, "snippet_3"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -318,7 +318,7 @@ describe("class tests in class.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], @@ -330,11 +330,11 @@ describe("class tests in class.test.ts", function () { ], [ [2, 1], [2, 0], [25, 0], [2, 2], - [24, "_1"], [24, "_2"], [2, 0], [2, 0], + [24, "snippet_1"], [24, "snippet_2"], [2, 0], [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_3"] + [2, 2], [24, "snippet_3"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); diff --git a/ts2panda/tests/types/function.test.ts b/ts2panda/tests/types/function.test.ts index 3003d42926..b6b640efcd 100644 --- a/ts2panda/tests/types/function.test.ts +++ b/ts2panda/tests/types/function.test.ts @@ -42,7 +42,7 @@ describe("function tests in function.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 3], [2, 0], [5, "local"], @@ -74,7 +74,7 @@ describe("function tests in function.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 3], [2, 0], [5, "multi_local"], @@ -109,7 +109,7 @@ describe("function tests in function.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 3], [24, "_1"], [24, "_2"], [24, "_3"], [2, 0] + [2, 3], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [2, 0] ], [ [2, 3], [2, 0], [5, "twoFunctions"], @@ -146,7 +146,7 @@ describe("function tests in function.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 3], [2, 0], [5, "localClass"], @@ -159,10 +159,10 @@ describe("function tests in function.test.ts", function () { [ [2, 3], [2, 0], [5, "foo"], [2, 0], - [2, 2], [25, 1], [24, "_4"], [25, 0] + [2, 2], [25, 1], [24, "snippet_4"], [25, 0] ], [ - [2, 2], [24, "_2"] + [2, 2], [24, "snippet_2"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); @@ -184,7 +184,7 @@ describe("function tests in function.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 3], [2, 0], [5, "localClassRet"], @@ -197,10 +197,10 @@ describe("function tests in function.test.ts", function () { ], [ [2, 3], [2, 0], [5, "foo"], - [2, 0], [2, 0], [24, "_4"] + [2, 0], [2, 0], [24, "snippet_4"] ], [ - [2, 2], [24, "_2"] + [2, 2], [24, "snippet_2"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); diff --git a/ts2panda/tests/types/object.test.ts b/ts2panda/tests/types/object.test.ts index bfaeef5ae8..600f68aa49 100644 --- a/ts2panda/tests/types/object.test.ts +++ b/ts2panda/tests/types/object.test.ts @@ -42,7 +42,7 @@ describe("object tests in object.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 1], [24, "_1"], [2, 0] + [2, 1], [24, "snippet_1"], [2, 0] ], [ [2, 6], [2, 2], [5, "a"], @@ -69,7 +69,7 @@ describe("object tests in object.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], @@ -77,10 +77,10 @@ describe("object tests in object.test.ts", function() { ], [ [2, 6], [2, 2], [5, "a"], - [24, "_3"], [5, "b"], [24, "_4"] + [24, "snippet_3"], [5, "b"], [24, "snippet_4"] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ], [ [2, 4], [2, 2], [25, 4], [25, 1] diff --git a/ts2panda/tests/types/primitives.test.ts b/ts2panda/tests/types/primitives.test.ts index 3603a83536..d7417cea10 100644 --- a/ts2panda/tests/types/primitives.test.ts +++ b/ts2panda/tests/types/primitives.test.ts @@ -79,7 +79,7 @@ describe("primitives tests in primitives.test.ts", function() { let expectedBuffValues = [ [ [2, 1], - [24, "_1"], + [24, "snippet_1"], [2, 0] ], [ @@ -171,7 +171,7 @@ describe("primitives tests in primitives.test.ts", function() { // check liberalBuffer let expectedBuffValues = [ [ - [2, 2], [24, "_1"], [24, "_2"], [2, 0] + [2, 2], [24, "snippet_1"], [24, "snippet_2"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], @@ -186,7 +186,7 @@ describe("primitives tests in primitives.test.ts", function() { [2, 0], [2, 0], [2, 0] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ] ] let buff = createLiteralBufferArray(expectedBuffValues); diff --git a/ts2panda/tests/types/union.test.ts b/ts2panda/tests/types/union.test.ts index 4d97791ae0..7b0be9553f 100644 --- a/ts2panda/tests/types/union.test.ts +++ b/ts2panda/tests/types/union.test.ts @@ -45,7 +45,7 @@ describe("union tests in union.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 4], [2, 2], [25, 1], [25, 2] @@ -81,17 +81,17 @@ describe("union tests in union.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0] ], [ - [2, 4], [2, 2], [24, "_3"], [24, "_4"] + [2, 4], [2, 2], [24, "snippet_3"], [24, "snippet_4"] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ], [ [2, 5], [25, 1] @@ -117,7 +117,7 @@ describe("union tests in union.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 1], [24, "_1"], [2, 0] + [2, 1], [24, "snippet_1"], [2, 0] ], [ [2, 4], [2, 2], [25, 1], [25, 2] @@ -144,17 +144,17 @@ describe("union tests in union.test.ts", function () { // check liberalBuffer let expectedBuffValues = [ [ - [2, 4], [24, "_1"], [24, "_2"], [24, "_3"], [24, "_4"], [2, 0] + [2, 4], [24, "snippet_1"], [24, "snippet_2"], [24, "snippet_3"], [24, "snippet_4"], [2, 0] ], [ [2, 1], [2, 0], [25, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0] ], [ - [2, 4], [2, 2], [24, "_3"], [24, "_4"] + [2, 4], [2, 2], [24, "snippet_3"], [24, "snippet_4"] ], [ - [2, 2], [24, "_1"] + [2, 2], [24, "snippet_1"] ], [ [2, 5], [25, 1] diff --git a/ts2panda/tests/utils/base.ts b/ts2panda/tests/utils/base.ts index 49c7c5b52d..201173ffd4 100644 --- a/ts2panda/tests/utils/base.ts +++ b/ts2panda/tests/utils/base.ts @@ -147,6 +147,7 @@ export function compileAllSnippet(snippet: string, passes?: Pass[], literalBuffe CmdOptions.isWatchEvaluateExpressionMode() ? setGlobalStrict(true) : setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions)); let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); + CompilerDriver.srcNode = sourceFile; if (!passes) { passes = []; @@ -192,6 +193,7 @@ export function compileAfterSnippet(snippet: string, name:string, isCommonJs: bo jshelpers.bindSourceFile(sourceFile, {}); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions)); let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); + CompilerDriver.srcNode = sourceFile; compilerDriver.setCustomPasses([]); compilerDriver.compileUnitTest(sourceFile, []); compileUnits = compilerDriver.getCompilationUnits(); diff --git a/ts2panda/tests/watch_expression/addWatch.test.ts b/ts2panda/tests/watch_expression/addWatch.test.ts index 7d00f48a70..6de1d64069 100644 --- a/ts2panda/tests/watch_expression/addWatch.test.ts +++ b/ts2panda/tests/watch_expression/addWatch.test.ts @@ -370,7 +370,7 @@ describe("WatchExpressions", function () { IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ - new Createarraywithbuffer(new Imm(0), "_1"), + new Createarraywithbuffer(new Imm(0), "snippet_1"), new Sta(new VReg()), new Lda(new VReg()), @@ -388,7 +388,7 @@ describe("WatchExpressions", function () { IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ - new Createobjectwithbuffer(new Imm(0), "_1"), + new Createobjectwithbuffer(new Imm(0), "snippet_1"), new Sta(new VReg()), new Lda(new VReg()), new Sta(new VReg()), @@ -946,7 +946,7 @@ describe("WatchExpressions", function () { let expected = [ new Mov(new VReg(), new VReg()), - new Defineclasswithbuffer(new Imm(0), "#1#", "_1", new Imm(0), new VReg()), + new Defineclasswithbuffer(new Imm(0), "#1#", "snippet_1", new Imm(0), new VReg()), new Sta(new VReg()), new Lda(new VReg()), new Sta(new VReg()), diff --git a/ts2panda/ts2abc/main.cpp b/ts2panda/ts2abc/main.cpp index c284060058..7e315e564c 100644 --- a/ts2panda/ts2abc/main.cpp +++ b/ts2panda/ts2abc/main.cpp @@ -49,6 +49,30 @@ int Preprocess(const panda::ts2abc::Options &options, const panda::PandArgParser return panda::ts2abc::RETURN_SUCCESS; } +bool HandleNpmEntries(const panda::ts2abc::Options &options, const panda::PandArgParser &argParser, + const std::string &usage) +{ + std::string input = options.GetTailArg1(); + std::string output = options.GetTailArg2(); + if (options.GetCompileByPipeArg() || input.empty() || output.empty()) { + if (options.GetCompileByPipeArg()) { + std::cerr << "[compile-npm-entries] and [compile-by-pipe] can not be used simultaneously" << std::endl; + } else { + std::cerr << "Incorrect args number" << std::endl; + } + std::cerr << "Usage example: js2abc --compile-npm-entries npm_entries.txt npm_entries.abc"<< std::endl; + std::cerr << usage << std::endl; + std::cerr << argParser.GetHelpString(); + return false; + } + + if (!panda::ts2abc::CompileNpmEntries(input, output)) { + return false; + } + + return true; +} + int main(int argc, const char *argv[]) { panda::PandArgParser argParser; @@ -76,6 +100,14 @@ int main(int argc, const char *argv[]) return panda::ts2abc::RETURN_SUCCESS; } + if (options.GetCompileNpmEntries()) { + if (!HandleNpmEntries(options, argParser, usage)) { + return panda::ts2abc::RETURN_FAILED; + } + return panda::ts2abc::RETURN_SUCCESS; + } + + if ((options.GetOptLevelArg() < static_cast(panda::ts2abc::OptLevel::O_LEVEL0)) || (options.GetOptLevelArg() > static_cast(panda::ts2abc::OptLevel::O_LEVEL2))) { std::cerr << "Incorrect optimization level value" << std::endl; diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 1cba8c9cb7..7df81efe62 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -52,13 +52,14 @@ std::string g_compilerOutputProto = ""; std::string g_recordName = ""; constexpr uint32_t LITERALBUFFERINDEXOFFSET = 100; uint32_t MAX_UINT8 = static_cast(std::numeric_limits::max()); +bool g_isOutputProto = false; +static constexpr const char* PROTO_BIN_SUFFIX = "protoBin"; constexpr std::size_t BOUND_LEFT = 0; constexpr std::size_t BOUND_RIGHT = 0; constexpr std::size_t LINE_NUMBER = 0; constexpr bool IS_DEFINED = true; int g_opCodeIndex = 0; -std::string g_recordName = ""; std::unordered_map g_opcodeMap = { #define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) {g_opCodeIndex++, panda::pandasm::Opcode::opcode}, PANDA_INSTRUCTION_LIST(OPLIST) @@ -826,8 +827,6 @@ static panda::pandasm::Function ParseFunction(const Json::Value &function, panda ParseSourceFileInfo(function, pandaFunc); ParseFunctionLabels(function, pandaFunc); ParseFunctionCatchTables(function, pandaFunc); - // parsing call opt type - ParseFunctionCallType(function, pandaFunc); ParseFunctionTypeInfo(function, pandaFunc, prog); ParseFunctionExportedType(function, pandaFunc, prog); ParseFunctionDeclaredType(function, pandaFunc, prog); @@ -975,10 +974,14 @@ static void ParseEnableTypeInfo(const Json::Value &rootValue) static void ParseCompilerOutputProto(const Json::Value &rootValue) { Logd("-----------------parse compiler output proto-----------------"); - if (rootValue.isMember("output-proto") && rootValue["output-proto"].isString()) { - g_compilerOutputProto = rootValue["output-proto"].asString(); + if (rootValue.isMember("output-proto") && rootValue["output-proto"].isBool()) { + g_isOutputProto = rootValue["output-proto"].asBool(); + } + if (rootValue.isMember("proto-name") && rootValue["proto-name"].isString()) { + g_compilerOutputProto = rootValue["proto-name"].asString(); } } + static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) { for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) { @@ -1173,7 +1176,7 @@ static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Pr auto typeInfoRecord = rootValue["ti"]; auto typeFlag = typeInfoRecord["tf"].asBool(); - auto typeSummaryIndex = typeInfoRecord["tsi"].asUInt(); + auto typeSummaryIndex = typeInfoRecord["tsi"].asString(); auto typeFlagField = panda::pandasm::Field(LANG_EXT); typeFlagField.name = "typeFlag"; @@ -1390,9 +1393,14 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string Logd("parsing done, calling pandasm\n"); - std::string compilerOutputProto = g_compilerOutputProto; if (options.GetCompilerOutputProto().size() > 0) { - compilerOutputProto = options.GetCompilerOutputProto(); + g_compilerOutputProto = options.GetCompilerOutputProto(); + } + + std::string compilerOutputProto = g_compilerOutputProto; + + if (compilerOutputProto.size() == 0 && g_isOutputProto) { + compilerOutputProto = output.substr(0, output.find_last_of(".") + 1).append(PROTO_BIN_SUFFIX); } #ifdef ENABLE_BYTECODE_OPT @@ -1446,6 +1454,52 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string return true; } +bool CompileNpmEntries(const std::string &input, const std::string &output) +{ + auto inputAbs = panda::os::file::File::GetAbsolutePath(input); + if (!inputAbs) { + std::cerr << "Input file does not exist" << std::endl; + return false; + } + auto fpath = inputAbs.Value(); + if (panda::os::file::File::IsRegularFile(fpath) == false) { + std::cerr << "Input must be either a regular file or a directory" << std::endl; + return false; + } + + std::stringstream ss; + std::ifstream inputStream(input); + if (inputStream.fail()) { + std::cerr << "Failed to read file to buffer: " << input << std::endl; + return false; + } + ss << inputStream.rdbuf(); + + panda::pandasm::Program prog = panda::pandasm::Program(); + prog.lang = LANG_EXT; + + std::string line; + while (getline(ss, line)) { + std::size_t pos = line.find(":"); + std::string recordName = line.substr(0, pos); + std::string field = line.substr(pos + 1); + + auto langExt = LANG_EXT; + auto entryNameField = panda::pandasm::Field(langExt); + entryNameField.name = field; + entryNameField.type = panda::pandasm::Type("u8", 0); + entryNameField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(0))); + + panda::pandasm::Record entryRecord = panda::pandasm::Record(recordName, langExt); + entryRecord.field_list.emplace_back(std::move(entryNameField)); + prog.record_table.emplace(recordName, std::move(entryRecord)); + } + + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, output); + return true; +} + bool HandleJsonFile(const std::string &input, std::string &data) { auto inputAbs = panda::os::file::File::GetAbsolutePath(input); diff --git a/ts2panda/ts2abc/ts2abc.h b/ts2panda/ts2abc/ts2abc.h index 4b4658dfdb..9288b91c27 100644 --- a/ts2panda/ts2abc/ts2abc.h +++ b/ts2panda/ts2abc/ts2abc.h @@ -51,6 +51,7 @@ enum class OptLevel { bool HandleJsonFile(const std::string &input, std::string &data); bool GenerateProgram(const std::string &data, const std::string &output, panda::ts2abc::Options options); +bool CompileNpmEntries(const std::string &input, const std::string &output); bool GetDebugLog(); void ParseLogEnable(const Json::Value &rootValue); bool GetDebugModeEnabled(); diff --git a/ts2panda/ts2abc/ts2abc_options.h b/ts2panda/ts2abc/ts2abc_options.h index 03d56e78e9..d4cfb330b5 100755 --- a/ts2panda/ts2abc/ts2abc_options.h +++ b/ts2panda/ts2abc/ts2abc_options.h @@ -39,7 +39,9 @@ namespace panda::ts2abc { parser->Add(&bc_version_arg_); parser->Add(&bc_min_version_arg_); parser->Add(&compile_by_pipe_arg_); + parser->Add(&compile_npm_entries_); parser->Add(&compiler_output_proto_); + parser->Add(&output_proto_name_); parser->EnableTail(); parser->PushBackTail(&Tail_Arg1_arg_); parser->PushBackTail(&Tail_Arg2_arg_); @@ -150,21 +152,51 @@ namespace panda::ts2abc { return compile_by_pipe_arg_.WasSet(); } - std::string GetCompilerOutputProto() const + bool GetCompileNpmEntries() const + { + return compile_npm_entries_.GetValue(); + } + + void SetCompileNpmEntries(bool value) + { + compile_npm_entries_.SetValue(value); + } + + bool WasSetCompileNpmEntries() const + { + return compile_npm_entries_.WasSet(); + } + + bool IsOutputProto() const { return compiler_output_proto_.GetValue(); } - void SetCompilerOutputProto(std::string value) + void SetOutputProto(bool value) { compiler_output_proto_.SetValue(value); } - bool WasSetCompilerOutputProto() const + bool WasSetOutputProto() const { return compiler_output_proto_.WasSet(); } + std::string GetCompilerOutputProto() const + { + return output_proto_name_.GetValue(); + } + + void SetCompilerOutputProto(std::string value) + { + output_proto_name_.SetValue(value); + } + + bool WasSetCompilerOutputProto() const + { + return output_proto_name_.WasSet(); + } + std::string GetTailArg1() const { return Tail_Arg1_arg_.GetValue(); @@ -223,7 +255,11 @@ namespace panda::ts2abc { R"(Print ark bytecode minimum supported version)"}; panda::PandArg compile_by_pipe_arg_{ "compile-by-pipe", false, R"(Compile a json file that is passed by pipe)"}; - panda::PandArg compiler_output_proto_{ "output-proto", "", + panda::PandArg compile_npm_entries_{ "compile-npm-entries", false, + R"(Compile npm entries info into an abc file)"}; + panda::PandArg compiler_output_proto_{ "output-proto", false, + R"(Output protoBin file)"}; + panda::PandArg output_proto_name_{ "proto-name", "", R"(Specify the output name for serializd protobuf file (.protoBin))"}; panda::PandArg Tail_Arg1_arg_{ "ARG_1", "", R"(Path to input(json file) or path to output(ark bytecode)" -- Gitee From 4dcfa360032daa565e1fc85d181c21bfa3d69e1b Mon Sep 17 00:00:00 2001 From: hufeng Date: Sat, 15 Oct 2022 20:43:22 +0800 Subject: [PATCH 10/59] Support merge-abc option in ts2abc Signed-off-by: hufeng Change-Id: Icfed901ec2defa044a512735dcc5e17a68afa1ba --- test262/run_sunspider.py | 12 +- ts2panda/scripts/generate_js_bytecode.py | 4 + ts2panda/src/base/util.ts | 2 +- ts2panda/src/cmdOptions.ts | 22 +++- ts2panda/src/compilerDriver.ts | 24 ++-- ts2panda/src/recorder.ts | 8 +- ts2panda/src/ts2panda.ts | 1 + ts2panda/tests/utils/base.ts | 15 ++- .../tests/watch_expression/addWatch.test.ts | 113 +++++------------- ts2panda/ts2abc/ts2abc.cpp | 110 ++++++++++++++--- 10 files changed, 189 insertions(+), 122 deletions(-) diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index cc3b9bd3b4..ce5bce3555 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -240,8 +240,9 @@ class ArkProgram(): cmd_args = [frontend_tool, dependency, '--outputProto', proto_bin_file, '--module', '--merge-abc'] else: + # for testing no-record-name abc cmd_args = [frontend_tool, dependency, '--output', output_abc, - '--module', '--merge-abc'] + '--module'] proc = subprocess.Popen(cmd_args) proc.wait() @@ -296,7 +297,7 @@ class ArkProgram(): self.abc_file = out_file mod_opt_index = 0 cmd_args = [] - dependency_cmd_args= [] + dependency_cmd_args = [] frontend_tool = self.ark_frontend_binary merge_abc_mode = self.merge_abc_mode dependencies = [] @@ -316,8 +317,9 @@ class ArkProgram(): cmd_args = ['node', '--expose-gc', frontend_tool, js_file, '--output-proto', '--merge-abc'] else: + # for testing no-record-name abc cmd_args = ['node', '--expose-gc', frontend_tool, - js_file, '-o', out_file, '--merge-abc'] + js_file, '-o', out_file] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "-m") self.module = True @@ -329,11 +331,11 @@ class ArkProgram(): str(self.es2abc_thread_count), '--outputProto', proto_bin_file, js_file, '--merge-abc'] else: - # '--merge-abc' should be removed when record-name is set as default in es2panda + # for testing no-record-name abc cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), '--function-threads=' + str(self.es2abc_thread_count), '--output', - out_file, js_file, '--merge-abc'] + out_file, js_file] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "--module") self.module = True diff --git a/ts2panda/scripts/generate_js_bytecode.py b/ts2panda/scripts/generate_js_bytecode.py index 2e7949cda3..0f4aca8823 100755 --- a/ts2panda/scripts/generate_js_bytecode.py +++ b/ts2panda/scripts/generate_js_bytecode.py @@ -48,6 +48,8 @@ def parse_args(): help='enable builtin types recognition for .d.ts files') parser.add_argument("--functionSourceCode", action='store_true', help='compile abc with function sourcecode info') + parser.add_argument("--merge-abc", action='store_true', + help='Compile as merge abc') arguments = parser.parse_args() return arguments @@ -100,6 +102,8 @@ def gen_abc_info(input_arguments): cmd.insert(7, '-b') if input_arguments.functionSourceCode: cmd.insert(8, '--function-sourcecode') + if input_arguments.merge_abc: + cmd.insert(9, '--merge-abc') run_command(cmd, path) diff --git a/ts2panda/src/base/util.ts b/ts2panda/src/base/util.ts index 25bf68deee..2453424609 100644 --- a/ts2panda/src/base/util.ts +++ b/ts2panda/src/base/util.ts @@ -410,7 +410,7 @@ export function getOutputBinName(node: ts.SourceFile) { export function getRecordName(node: ts.SourceFile): string { let recordName = CmdOptions.getRecordName(); - if (recordName == "") { + if (recordName == "" && CmdOptions.isMergeAbc()) { let outputBinName = getOutputBinName(node); recordName = path.basename(outputBinName, path.extname(outputBinName)); } diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index b746fdf986..32829c8d0a 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -51,9 +51,10 @@ const ts2pandaOptions = [ { name: 'expression-watch-toolchain', type: String, defaultValue: "es2panda", description: "Specify the tool chain used to transform the expression" }, { name: 'source-file', type: String, defaultValue: "", description: "specify the file path info recorded in generated abc" }, { name: 'generate-tmp-file', type: Boolean, defaultValue: false, description: "whether to generate intermediate temporary files"}, - { name: 'record-name', type: String, defaultValue: "", description: "specify the record name." }, + { name: 'record-name', type: String, defaultValue: "", description: "specify the record name, this option can only be used when [merge-abc] is enabled." }, { name: 'output-proto', type: Boolean, defaultValue: false, description: "Output protoBin file. Default: false" }, { name: 'proto-name', type: String, defaultValue: "", description: "specify the output name for serializd protobuf file (.protoBin)" }, + { name: 'merge-abc', type: Boolean, defaultValue: false, description: "Compile as merge abc" }, ] @@ -212,10 +213,22 @@ export class CmdOptions { return outputFile; } + static setMergeAbc(mergeAbcMode: Boolean): void { + if (!this.options) { + return; + } + this.options["merge-abc"] = mergeAbcMode; + } + static getRecordName(): string { if (!this.options) { return ""; } + + if (!this.options["merge-abc"]) { + return ""; + } + return this.options["record-name"]; } @@ -339,6 +352,13 @@ export class CmdOptions { return this.options["proto-name"]; } + static isMergeAbc(): boolean { + if (!this.options) { + return false; + } + return this.options["merge-abc"] + } + // @ts-ignore static parseUserCmd(args: string[]): ts.ParsedCommandLine | undefined { this.options = commandLineArgs(ts2pandaOptions, { partial: true }); diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index 00164490d6..8409b71ab9 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -186,8 +186,10 @@ export class CompilerDriver { listenErrorEvent(ts2abcProc); try { - // must keep [dumpRecord] at first - Ts2Panda.dumpRecord(ts2abcProc, this.recordName); + if (CmdOptions.isMergeAbc()) { + // must keep [dumpRecord] at first + Ts2Panda.dumpRecord(ts2abcProc, this.recordName); + } Ts2Panda.dumpCmdOptions(ts2abcProc); for (let i = 0; i < this.pendingCompilationUnits.length; i++) { @@ -360,6 +362,14 @@ export class CompilerDriver { return idx; } + getFormatedRecordName() { + let formatedRecordName: string = ''; + if (CmdOptions.isMergeAbc()) { + formatedRecordName = this.recordName + '.'; + } + return formatedRecordName; + } + /** * Internal name is used to indentify a function in panda file * Runtime uses this name to bind code and a Function object @@ -377,13 +387,13 @@ export class CompilerDriver { if (name == '') { if ((ts.isFunctionDeclaration(node) && hasExportKeywordModifier(node) && hasDefaultKeywordModifier(node)) || ts.isExportAssignment(findOuterNodeOfParenthesis(node))) { - return `${this.recordName}.default`; + return `${this.getFormatedRecordName()}default`; } - return `${this.recordName}.#${this.getFuncId(funcNode)}#`; + return `${this.getFormatedRecordName()}#${this.getFuncId(funcNode)}#`; } if (name == "func_main_0") { - return `${this.recordName}.#${this.getFuncId(funcNode)}#${name}`; + return `${this.getFormatedRecordName()}#${this.getFuncId(funcNode)}#${name}`; } let funcNameMap = recorder.getFuncNameMap(); @@ -400,7 +410,7 @@ export class CompilerDriver { name = `#${this.getFuncId(funcNode)}#` } } - return `${this.recordName}.${name}`; + return `${this.getFormatedRecordName()}${name}`; } getInternalNameForCtor(node: ts.ClassLikeDeclaration, ctor: ts.ConstructorDeclaration) { @@ -409,7 +419,7 @@ export class CompilerDriver { if (name.lastIndexOf(".") != -1) { name = `#${this.getFuncId(ctor)}#` } - return `${this.recordName}.${name}`; + return `${this.getFormatedRecordName()}${name}`; } writeBinaryFile(pandaGen: PandaGen) { diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index 866ed784d9..2f3881b13d 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -458,11 +458,11 @@ export class Recorder { return exportStmt; } - private getNormalizeModuleSpecifier(moduleSpecifier: ts.Expression): string { + private getModuleSpecifier(moduleSpecifier: ts.Expression): string { if (!ts.isStringLiteral(moduleSpecifier)) { throw new Error("moduleSpecifier must be a stringLiteral"); } - return path.normalize(jshelpers.getTextOfIdentifierOrLiteral(moduleSpecifier)); + return jshelpers.getTextOfIdentifierOrLiteral(moduleSpecifier); } private recordEcmaNamedBindings(namedBindings: ts.NamedImportBindings, scope: ModuleScope, moduleRequest: string) { @@ -506,7 +506,7 @@ export class Recorder { return; } - let moduleRequest: string = this.getNormalizeModuleSpecifier(node.moduleSpecifier); + let moduleRequest: string = this.getModuleSpecifier(node.moduleSpecifier); if (node.importClause) { let importClause: ts.ImportClause = node.importClause; @@ -519,7 +519,7 @@ export class Recorder { private recordEcmaExportDecl(node: ts.ExportDeclaration, scope: ModuleScope) { if (node.moduleSpecifier) { - let moduleRequest: string = this.getNormalizeModuleSpecifier(node.moduleSpecifier); + let moduleRequest: string = this.getModuleSpecifier(node.moduleSpecifier); if (node.exportClause) { let namedBindings: ts.NamedExportBindings = node.exportClause; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 05546247ab..8f1e9dfbcc 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -216,6 +216,7 @@ export class Ts2Panda { let enableRecordType: boolean = CmdOptions.needRecordType() && CompilerDriver.isTsFile; let options = { "t": JsonType.options, + "merge_abc": CmdOptions.isMergeAbc(), "module_mode": CmdOptions.isModules(), "commonjs_module": CmdOptions.isCommonJs(), "debug_mode": CmdOptions.isDebugMode(), diff --git a/ts2panda/tests/utils/base.ts b/ts2panda/tests/utils/base.ts index 201173ffd4..31017db4ad 100644 --- a/ts2panda/tests/utils/base.ts +++ b/ts2panda/tests/utils/base.ts @@ -141,9 +141,15 @@ export function checkInstructions(actual: IRNode[], expected: IRNode[], checkFn? return true; } -export function compileAllSnippet(snippet: string, passes?: Pass[], literalBufferArray?: Array): PandaGen[] { +export function compileAllSnippet(snippet: string, passes?: Pass[], literalBufferArray?: Array, + isWatchEvaluateExpressionMode?: boolean): PandaGen[] { let sourceFile = creatAstFromSnippet(snippet); jshelpers.bindSourceFile(sourceFile, {}); + CmdOptions.parseUserCmd([""]); + if (isWatchEvaluateExpressionMode) { + CmdOptions.setWatchEvaluateExpressionArgs(['','']); + } + CmdOptions.setMergeAbc(true); CmdOptions.isWatchEvaluateExpressionMode() ? setGlobalStrict(true) : setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions)); let compilerDriver = new CompilerDriver('UnitTest', 'UnitTest'); @@ -157,8 +163,9 @@ export function compileAllSnippet(snippet: string, passes?: Pass[], literalBuffe return compilerDriver.getCompilationUnits(); } -export function compileMainSnippet(snippet: string, pandaGen?: PandaGen, scope?: Scope, passes?: Pass[], compileFunc?: boolean): IRNode[] { - let compileUnits = compileAllSnippet(snippet, passes); +export function compileMainSnippet(snippet: string, pandaGen?: PandaGen, scope?: Scope, passes?: Pass[], + compileFunc?: boolean, isWatchEvaluateExpressionMode?: boolean): IRNode[] { + let compileUnits = compileAllSnippet(snippet, passes, undefined, isWatchEvaluateExpressionMode); if (compileUnits.length != 1 && !compileFunc) { throw new Error("Error: please use compileMainSnippet1 for multi function compile"); @@ -176,6 +183,8 @@ export function compileMainSnippet(snippet: string, pandaGen?: PandaGen, scope?: export function compileAfterSnippet(snippet: string, name:string, isCommonJs: boolean = false) { let compileUnits = null; + CmdOptions.parseUserCmd([""]); + CmdOptions.setMergeAbc(true); ts.transpileModule( snippet, { diff --git a/ts2panda/tests/watch_expression/addWatch.test.ts b/ts2panda/tests/watch_expression/addWatch.test.ts index 6de1d64069..586e49acf2 100644 --- a/ts2panda/tests/watch_expression/addWatch.test.ts +++ b/ts2panda/tests/watch_expression/addWatch.test.ts @@ -70,11 +70,9 @@ import { checkInstructions, compileMainSnippet, compileAllSnippet } from "../uti describe("WatchExpressions", function () { it("watch NumericLiteral", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a=-123.212 - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -98,11 +96,9 @@ describe("WatchExpressions", function () { }); it("watch StringLiteral", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` y = 'He is called \'Johnny\'' - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -131,11 +127,9 @@ describe("WatchExpressions", function () { }); it("watch RegularExpressionLiteral", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a = /abc/ - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -155,11 +149,9 @@ describe("WatchExpressions", function () { }); it("watch Identifier", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` _awef - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -178,11 +170,9 @@ describe("WatchExpressions", function () { }); it("watch TrueKeyword", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` b === true - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let isTrueLabel = new Label(); @@ -212,11 +202,9 @@ describe("WatchExpressions", function () { }); it("watch FalseKeyword", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` b === false - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let ifFalseLabel = new Label(); //lable0 @@ -247,11 +235,9 @@ describe("WatchExpressions", function () { }); it("watch CallExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` BigInt(10.2) - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -275,11 +261,9 @@ describe("WatchExpressions", function () { }); it("watch NullKeyword", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` b === null - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let isTrueLabel = new Label(); @@ -309,11 +293,9 @@ describe("WatchExpressions", function () { }); it("watch ThisKeyword", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` this - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -332,13 +314,11 @@ describe("WatchExpressions", function () { }); it("watch MetaProperty", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet(` function (){ b = new.target; } - `); + `, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -362,11 +342,9 @@ describe("WatchExpressions", function () { }); it("watch ArrayLiteralExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` [1,2] - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -380,11 +358,9 @@ describe("WatchExpressions", function () { }); it("watch ObjectLiteralExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a = {key:1,value:1} - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -406,11 +382,9 @@ describe("WatchExpressions", function () { }); it("watch PropertyAccessExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a.b - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -432,11 +406,9 @@ describe("WatchExpressions", function () { }); it("watch ElementAccessExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a[0] - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -458,11 +430,9 @@ describe("WatchExpressions", function () { }); it("watch NewExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` new Function() - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -483,11 +453,9 @@ describe("WatchExpressions", function () { }); it("watch ParenthesizedExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` (a,b,c) - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -524,11 +492,9 @@ describe("WatchExpressions", function () { }); it("watch FunctionExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet(` a = function () {} - `); + `, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -552,11 +518,9 @@ describe("WatchExpressions", function () { }); it("watch DeleteExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` delete[abc] - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -580,11 +544,9 @@ describe("WatchExpressions", function () { }); it("watch TypeOfExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` typeof(a) - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -604,11 +566,9 @@ describe("WatchExpressions", function () { }); it("watch VoidExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` void doSomething() - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -631,13 +591,10 @@ describe("WatchExpressions", function () { }); it("watch AwaitExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet( `async function a(){ await abc; - }` - ); + }`, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let beginLabel = new Label(); @@ -689,11 +646,9 @@ describe("WatchExpressions", function () { }); it("watch PrefixUnaryExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` --a - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -723,11 +678,9 @@ describe("WatchExpressions", function () { }); it("watch PostfixUnaryExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a-- - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -759,11 +712,9 @@ describe("WatchExpressions", function () { }); it("watch BinaryExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a+b - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -792,11 +743,9 @@ describe("WatchExpressions", function () { }); it("watch ConditionalExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let insns = compileMainSnippet(` a?4:2 - `); + `, undefined, undefined, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let ifTrueLabel = new Label(); @@ -825,12 +774,10 @@ describe("WatchExpressions", function () { }); it("watch YieldExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet(` function* func(){ yield a; - }`); + }`, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let startLabel = new Label(); @@ -904,11 +851,9 @@ describe("WatchExpressions", function () { }); it("watch ArrowFunction", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet(` a => b.length - `); + `, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ @@ -937,11 +882,9 @@ describe("WatchExpressions", function () { }); it("watch ClassExpression", function () { - CmdOptions.parseUserCmd([""]); - CmdOptions.setWatchEvaluateExpressionArgs(['','']); let pandaGens = compileAllSnippet(` a = new class{}; - `); + `, undefined, undefined, true); IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); let expected = [ diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 7df81efe62..073db29293 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -37,6 +37,7 @@ namespace panda::ts2abc { // pandasm definitions constexpr const auto LANG_EXT = panda::pandasm::extensions::Language::ECMASCRIPT; const std::string WHOLE_LINE; +bool g_isMergeAbc = false; bool g_debugModeEnabled = false; bool g_debugLogEnabled = false; int g_optLevel = 0; @@ -178,8 +179,12 @@ static std::string GetLiteralId(int64_t index) return g_recordName + "_" + std::to_string(index); } -static bool IsFuncMain0(std::string funcName) { - std::string expectedName = g_recordName + ".func_main_0"; +static bool IsFuncMain0(std::string funcName) +{ + std::string expectedName = "func_main_0"; + if (g_isMergeAbc) { + expectedName = g_recordName + "." + expectedName; + } return funcName == expectedName; } @@ -855,6 +860,28 @@ static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog) prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord)); } +static void GenerateESModuleRecord(panda::pandasm::Program &prog) +{ + auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT); + ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); + prog.record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord)); +} + +static void GenerateCommonJsRecord(panda::pandasm::Program &prog, bool isCommonJs) +{ + // when multi-abc file get merged, field should be inserted in abc's own record + auto commonjsRecord = panda::pandasm::Record("_CommonJsRecord", LANG_EXT); + commonjsRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); + auto isCommonJsField = panda::pandasm::Field(LANG_EXT); + isCommonJsField.name = "isCommonJs"; + isCommonJsField.type = panda::pandasm::Type("u8", 0); + isCommonJsField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(isCommonJs))); + commonjsRecord.field_list.emplace_back(std::move(isCommonJsField)); + + prog.record_table.emplace(commonjsRecord.name, std::move(commonjsRecord)); +} + static void SetCommonjsField(panda::pandasm::Program &prog, bool isCommonjs) { auto iter = prog.record_table.find(g_recordName); @@ -871,11 +898,13 @@ static void SetCommonjsField(panda::pandasm::Program &prog, bool isCommonjs) static void AddModuleRecord(panda::pandasm::Program &prog, const std::string &moduleName) { - auto iter = prog.record_table.find(g_recordName); + std::string moduleRecordName = g_isMergeAbc ? g_recordName : "_ESModuleRecord"; + std::string fieldName = g_isMergeAbc ? "moduleRecordIdx" : moduleName; + auto iter = prog.record_table.find(moduleRecordName); if (iter != prog.record_table.end()) { auto &rec = iter->second; auto moduleIdxField = panda::pandasm::Field(LANG_EXT); - moduleIdxField.name = "moduleRecordIdx"; + moduleIdxField.name = fieldName; moduleIdxField.type = panda::pandasm::Type("u32", 0); std::string moduleId = GetLiteralId(g_newLiteralArrayIndex); moduleIdxField.metadata->SetValue( @@ -905,11 +934,35 @@ int ParseJson(const std::string &data, Json::Value &rootValue) return RETURN_SUCCESS; } -static void SetCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) +static void ParseMergeAbcMode(const Json::Value &rootValue) +{ + Logd("---------------parse is_merge_abc----------------"); + if (rootValue.isMember("merge_abc") && rootValue["merge_abc"].isBool()) { + g_isMergeAbc = rootValue["merge_abc"].asBool(); + } +} + +static void ParseModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) +{ + Logd("----------------parse module_mode-----------------"); + if (rootValue.isMember("module_mode") && rootValue["module_mode"].isBool()) { + if (rootValue["module_mode"].asBool() && !g_isMergeAbc) { + GenerateESModuleRecord(prog); + } + } +} + +static void ParseCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog) { Logd("------------parse commonjs_module_mode-------------"); if (rootValue.isMember("commonjs_module") && rootValue["commonjs_module"].isBool()) { - SetCommonjsField(prog, rootValue["commonjs_module"].asBool()); + if (g_isMergeAbc) { + SetCommonjsField(prog, rootValue["commonjs_module"].asBool()); + } else { + if (rootValue["commonjs_module"].asBool()) { + GenerateCommonJsRecord(prog, true); + } + } } } @@ -997,7 +1050,9 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & { GenerateESCallTypeAnnotationRecord(prog); GenerateESTypeAnnotationRecord(prog); - SetCommonJsModuleMode(rootValue, prog); + ParseMergeAbcMode(rootValue); + ParseModuleMode(rootValue, prog); + ParseCommonJsModuleMode(rootValue, prog); ParseLogEnable(rootValue); ParseDebugMode(rootValue); ParseOptLevel(rootValue); @@ -1170,20 +1225,41 @@ static void ParseSingleModule(const Json::Value &rootValue, panda::pandasm::Prog static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Program &prog) { - auto iter = prog.record_table.find(g_recordName); - if (iter != prog.record_table.end()) { - auto &rec = iter->second; - - auto typeInfoRecord = rootValue["ti"]; - auto typeFlag = typeInfoRecord["tf"].asBool(); - auto typeSummaryIndex = typeInfoRecord["tsi"].asString(); + auto typeInfoRecord = rootValue["ti"]; + auto typeFlag = typeInfoRecord["tf"].asBool(); + auto typeSummaryIndex = typeInfoRecord["tsi"].asString(); + + if (g_isMergeAbc) { + auto iter = prog.record_table.find(g_recordName); + if (iter != prog.record_table.end()) { + auto &rec = iter->second; + + auto typeFlagField = panda::pandasm::Field(LANG_EXT); + typeFlagField.name = "typeFlag"; + typeFlagField.type = panda::pandasm::Type("u8", 0); + typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(typeFlag))); + rec.field_list.emplace_back(std::move(typeFlagField)); + + if (g_enableTypeinfo) { + auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); + typeSummaryIndexField.name = "typeSummaryOffset"; + typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); + typeSummaryIndexField.metadata->SetValue( + panda::pandasm::ScalarValue::Create(typeSummaryIndex)); + rec.field_list.emplace_back(std::move(typeSummaryIndexField)); + } + } + } else { + auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT); + ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); auto typeFlagField = panda::pandasm::Field(LANG_EXT); typeFlagField.name = "typeFlag"; typeFlagField.type = panda::pandasm::Type("u8", 0); typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( static_cast(typeFlag))); - rec.field_list.emplace_back(std::move(typeFlagField)); + ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField)); if (g_enableTypeinfo) { auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); @@ -1191,8 +1267,10 @@ static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Pr typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); typeSummaryIndexField.metadata->SetValue( panda::pandasm::ScalarValue::Create(typeSummaryIndex)); - rec.field_list.emplace_back(std::move(typeSummaryIndexField)); + ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField)); } + + prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord)); } } -- Gitee From bccf8c7b474175db42bc356c87594e57164f3f62 Mon Sep 17 00:00:00 2001 From: songqi Date: Wed, 12 Oct 2022 18:06:47 +0800 Subject: [PATCH 11/59] Fix not updating KeyWordType when scanning nextToken Issue: I5VDE6 Test: test262, parser tests, compiler tests, tsc Signed-off-by: songqi Change-Id: I496b1bcb893620a702bbc01ae61be5284827cbad --- es2panda/ir/base/scriptFunction.cpp | 1 + es2panda/lexer/lexer.cpp | 2 + es2panda/parser/parserImpl.cpp | 6 +- .../test-arguments-1-expected.txt | 1 + .../arguments-object/test-arguments-1.js | 18 + .../ts/test-class-definiton19-expected.txt | 585 ++++++++++++++++++ .../test/parser/ts/test-class-definiton19.ts | 21 + es2panda/test/test_tsc_ignore_list.txt | 1 - 8 files changed, 631 insertions(+), 4 deletions(-) create mode 100644 es2panda/test/parser/js/language/arguments-object/test-arguments-1-expected.txt create mode 100644 es2panda/test/parser/js/language/arguments-object/test-arguments-1.js create mode 100644 es2panda/test/parser/ts/test-class-definiton19-expected.txt create mode 100644 es2panda/test/parser/ts/test-class-definiton19.ts diff --git a/es2panda/ir/base/scriptFunction.cpp b/es2panda/ir/base/scriptFunction.cpp index 3716b630cc..ba8d968fc5 100644 --- a/es2panda/ir/base/scriptFunction.cpp +++ b/es2panda/ir/base/scriptFunction.cpp @@ -88,6 +88,7 @@ void ScriptFunction::Dump(ir::AstDumper *dumper) const {"generator", IsGenerator()}, {"async", IsAsync()}, {"expression", ((flags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0)}, + {"thisParam", AstDumper::Optional(thisParam_)}, {"params", params_}, {"returnType", AstDumper::Optional(returnTypeAnnotation_)}, {"typeParameters", AstDumper::Optional(typeParams_)}, diff --git a/es2panda/lexer/lexer.cpp b/es2panda/lexer/lexer.cpp index bd7b785c80..5e80b9718e 100644 --- a/es2panda/lexer/lexer.cpp +++ b/es2panda/lexer/lexer.cpp @@ -1310,6 +1310,8 @@ void Lexer::NextToken(LexerNextTokenFlags flags) auto cp = Iterator().Peek(); Iterator().Forward(1); + GetToken().keywordType_ = TokenType::EOS; + switch (cp) { case LEX_CHAR_EXCLAMATION: { ScanExclamationPunctuator(); diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 09a79b3c26..4fa6a28421 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -3396,10 +3396,10 @@ void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) { switch (node->Type()) { case ir::AstNodeType::IDENTIFIER: { - // Check the prevoius ident keyword type - if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS) { + // Check the prevoius ident name + if (node->AsIdentifier()->Name().Is("arguments")) { ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid"); - } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL) { + } else if (node->AsIdentifier()->Name().Is("eval")) { ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid"); } break; diff --git a/es2panda/test/parser/js/language/arguments-object/test-arguments-1-expected.txt b/es2panda/test/parser/js/language/arguments-object/test-arguments-1-expected.txt new file mode 100644 index 0000000000..1d8949e3ee --- /dev/null +++ b/es2panda/test/parser/js/language/arguments-object/test-arguments-1-expected.txt @@ -0,0 +1 @@ +SyntaxError: Assigning to 'arguments' in strict mode is invalid [test.js:1:11] diff --git a/es2panda/test/parser/js/language/arguments-object/test-arguments-1.js b/es2panda/test/parser/js/language/arguments-object/test-arguments-1.js new file mode 100644 index 0000000000..6cd2a29628 --- /dev/null +++ b/es2panda/test/parser/js/language/arguments-object/test-arguments-1.js @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +"use strict"; +arguments = 7; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-class-definiton19-expected.txt b/es2panda/test/parser/ts/test-class-definiton19-expected.txt new file mode 100644 index 0000000000..2591929740 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton19-expected.txt @@ -0,0 +1,585 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "method", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 11 + } + } + }, + "kind": "method", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "thisParam": { + "type": "Identifier", + "name": "this", + "typeAnnotation": { + "type": "TSThisType", + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "params": [ + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 41 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 31 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 43 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "method1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 12 + } + } + }, + "kind": "method", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "thisParam": { + "type": "Identifier", + "name": "this", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 17 + } + } + }, + "params": [ + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 19, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 19, + "column": 36 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 19, + "column": 26 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 19, + "column": 38 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "method2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 12 + } + } + }, + "kind": "method", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 20 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 20, + "column": 32 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 34 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/ts/test-class-definiton19.ts b/es2panda/test/parser/ts/test-class-definiton19.ts new file mode 100644 index 0000000000..cc97a38e52 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton19.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + method(this: this, ...args: number[]) {} + method1(this, ...args: number[]) {} + method2(...args: number[]) {} +} \ No newline at end of file diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..260d3e45c5 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -16,7 +16,6 @@ es2panda/test/TypeScript/tests/cases/compiler/declareIdentifierAsBeginningOfStat es2panda/test/TypeScript/tests/cases/compiler/discriminantsAndPrimitives.ts es2panda/test/TypeScript/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts es2panda/test/TypeScript/tests/cases/compiler/emitBundleWithShebang1.ts -es2panda/test/TypeScript/tests/cases/compiler/emitDecoratorMetadata_restArgs.ts es2panda/test/TypeScript/tests/cases/compiler/exportAsNamespace.d.ts es2panda/test/TypeScript/tests/cases/compiler/exportDeclarationsInAmbientNamespaces.ts es2panda/test/TypeScript/tests/cases/compiler/exportEqualsOfModule.ts -- Gitee From 2d9ad8075271ba2f677c90684ec6e7ee3dbea7d7 Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Thu, 20 Oct 2022 18:45:31 +0800 Subject: [PATCH 12/59] Fix comments Signed-off-by: gavin1012_hw Change-Id: I57434eab0b437086f7e4f167137a2710ffffc903 --- ts2panda/src/cmdOptions.ts | 8 ----- ts2panda/src/ts2panda.ts | 1 - ts2panda/ts2abc/ts2abc.cpp | 61 ++++++++++++++------------------ ts2panda/ts2abc/ts2abc_options.h | 18 ---------- 4 files changed, 26 insertions(+), 62 deletions(-) diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 32829c8d0a..99a1539d77 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -53,7 +53,6 @@ const ts2pandaOptions = [ { name: 'generate-tmp-file', type: Boolean, defaultValue: false, description: "whether to generate intermediate temporary files"}, { name: 'record-name', type: String, defaultValue: "", description: "specify the record name, this option can only be used when [merge-abc] is enabled." }, { name: 'output-proto', type: Boolean, defaultValue: false, description: "Output protoBin file. Default: false" }, - { name: 'proto-name', type: String, defaultValue: "", description: "specify the output name for serializd protobuf file (.protoBin)" }, { name: 'merge-abc', type: Boolean, defaultValue: false, description: "Compile as merge abc" }, ] @@ -345,13 +344,6 @@ export class CmdOptions { return this.options["output-proto"]; } - static getProtoName(): string { - if (!this.options) { - return ""; - } - return this.options["proto-name"]; - } - static isMergeAbc(): boolean { if (!this.options) { return false; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 8f1e9dfbcc..629511fd0e 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -226,7 +226,6 @@ export class Ts2Panda { "display_typeinfo": CmdOptions.getDisplayTypeinfo(), "is_dts_file": isGlobalDeclare(), "output-proto": CmdOptions.isOutputproto(), - "proto-name": CmdOptions.getProtoName(), "record_type": enableRecordType }; let jsonOpt = JSON.stringify(options, null, 2); diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 073db29293..2e564efc01 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -1030,9 +1030,6 @@ static void ParseCompilerOutputProto(const Json::Value &rootValue) if (rootValue.isMember("output-proto") && rootValue["output-proto"].isBool()) { g_isOutputProto = rootValue["output-proto"].asBool(); } - if (rootValue.isMember("proto-name") && rootValue["proto-name"].isString()) { - g_compilerOutputProto = rootValue["proto-name"].asString(); - } } static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) @@ -1250,28 +1247,28 @@ static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Pr rec.field_list.emplace_back(std::move(typeSummaryIndexField)); } } - } else { - auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT); - ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); - - auto typeFlagField = panda::pandasm::Field(LANG_EXT); - typeFlagField.name = "typeFlag"; - typeFlagField.type = panda::pandasm::Type("u8", 0); - typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( - static_cast(typeFlag))); - ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField)); - - if (g_enableTypeinfo) { - auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); - typeSummaryIndexField.name = "typeSummaryOffset"; - typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); - typeSummaryIndexField.metadata->SetValue( - panda::pandasm::ScalarValue::Create(typeSummaryIndex)); - ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField)); - } + return; + } + auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT); + ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); + + auto typeFlagField = panda::pandasm::Field(LANG_EXT); + typeFlagField.name = "typeFlag"; + typeFlagField.type = panda::pandasm::Type("u8", 0); + typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(typeFlag))); + ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField)); - prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord)); + if (g_enableTypeinfo) { + auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT); + typeSummaryIndexField.name = "typeSummaryOffset"; + typeSummaryIndexField.type = panda::pandasm::Type("u32", 0); + typeSummaryIndexField.metadata->SetValue( + panda::pandasm::ScalarValue::Create(typeSummaryIndex)); + ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField)); } + + prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord)); } static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Program &prog) @@ -1471,14 +1468,8 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string Logd("parsing done, calling pandasm\n"); - if (options.GetCompilerOutputProto().size() > 0) { - g_compilerOutputProto = options.GetCompilerOutputProto(); - } - - std::string compilerOutputProto = g_compilerOutputProto; - - if (compilerOutputProto.size() == 0 && g_isOutputProto) { - compilerOutputProto = output.substr(0, output.find_last_of(".") + 1).append(PROTO_BIN_SUFFIX); + if (g_isOutputProto) { + g_compilerOutputProto = output.substr(0, output.find_last_of(".") + 1).append(PROTO_BIN_SUFFIX); } #ifdef ENABLE_BYTECODE_OPT @@ -1506,8 +1497,8 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string panda::bytecodeopt::OptimizeBytecode(&prog, mapsp, output.c_str(), true); - if (compilerOutputProto.size() > 0) { - panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, compilerOutputProto); + if (g_compilerOutputProto.size() > 0) { + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto); return true; } @@ -1518,8 +1509,8 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string return true; } #endif - if (compilerOutputProto.size() > 0) { - panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, compilerOutputProto); + if (g_compilerOutputProto.size() > 0) { + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto); return true; } diff --git a/ts2panda/ts2abc/ts2abc_options.h b/ts2panda/ts2abc/ts2abc_options.h index d4cfb330b5..41dafe7c45 100755 --- a/ts2panda/ts2abc/ts2abc_options.h +++ b/ts2panda/ts2abc/ts2abc_options.h @@ -41,7 +41,6 @@ namespace panda::ts2abc { parser->Add(&compile_by_pipe_arg_); parser->Add(&compile_npm_entries_); parser->Add(&compiler_output_proto_); - parser->Add(&output_proto_name_); parser->EnableTail(); parser->PushBackTail(&Tail_Arg1_arg_); parser->PushBackTail(&Tail_Arg2_arg_); @@ -182,21 +181,6 @@ namespace panda::ts2abc { return compiler_output_proto_.WasSet(); } - std::string GetCompilerOutputProto() const - { - return output_proto_name_.GetValue(); - } - - void SetCompilerOutputProto(std::string value) - { - output_proto_name_.SetValue(value); - } - - bool WasSetCompilerOutputProto() const - { - return output_proto_name_.WasSet(); - } - std::string GetTailArg1() const { return Tail_Arg1_arg_.GetValue(); @@ -259,8 +243,6 @@ namespace panda::ts2abc { R"(Compile npm entries info into an abc file)"}; panda::PandArg compiler_output_proto_{ "output-proto", false, R"(Output protoBin file)"}; - panda::PandArg output_proto_name_{ "proto-name", "", - R"(Specify the output name for serializd protobuf file (.protoBin))"}; panda::PandArg Tail_Arg1_arg_{ "ARG_1", "", R"(Path to input(json file) or path to output(ark bytecode)" " when 'compile-by-pipe' enabled)"}; -- Gitee From 4579ab0159c76f751b3b2e4ea34e0b0c67ab86fe Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Wed, 12 Oct 2022 16:27:59 +0800 Subject: [PATCH 13/59] Fix no-name for autoGenerated Identifier in ts2panda Related Issue: I5VBME Signed-off-by: gavin1012_hw Change-Id: I381a62f7e101d100fe715c948d178b2e25dcf532 --- ts2panda/src/base/lreference.ts | 7 ++++++- ts2panda/src/index.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ts2panda/src/base/lreference.ts b/ts2panda/src/base/lreference.ts index e27363aee3..b079b70bb8 100644 --- a/ts2panda/src/base/lreference.ts +++ b/ts2panda/src/base/lreference.ts @@ -139,7 +139,12 @@ export class LReference { let name = jshelpers.getTextOfIdentifierOrLiteral(realNode); let variable = compiler.getCurrentScope().find(name); if (!variable.v) { - variable.v = compiler.getCurrentScope().add(name, VarDeclarationKind.NONE); + // @ts-ignore + if (ts.isGeneratedIdentifier(realNode)) { + variable.v = compiler.getCurrentScope().add(name, VarDeclarationKind.VAR); + } else { + variable.v = compiler.getCurrentScope().add(name, VarDeclarationKind.NONE); + } } return new LReference(realNode, compiler, isDeclaration, ReferenceKind.LocalOrGlobal, variable); diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 61f2dbfed0..7fb5dca084 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -110,6 +110,8 @@ function main(fileNames: string[], options: ts.CompilerOptions) { // @ts-ignore (ctx: ts.TransformationContext) => { return (node: ts.SourceFile) => { + makeAutoGeneratedNodeName(node); + if (ts.getEmitHelpers(node)) { let newStatements = []; ts.getEmitHelpers(node)?.forEach( @@ -153,6 +155,30 @@ function main(fileNames: string[], options: ts.CompilerOptions) { }); } +let generatedVarId = 0; + +function makeAutoGeneratedNodeName(node: ts.Node) { + node.forEachChild(childNode => { + switch (childNode.kind) { + case ts.SyntaxKind.Identifier: { + // @ts-ignore + if (ts.isGeneratedIdentifier(childNode) && (childNode).escapedText == "") { + if (generatedVarId < 26) { // #a ~ #z + // @ts-ignore + (childNode).escapedText = "#" + String.fromCharCode(97 /* a */ + generatedVarId); + } else { + // @ts-ignore + (childNode).escapedText = "#" + (generatedVarId - 26); + } + generatedVarId++; + } + break; + } + } + makeAutoGeneratedNodeName(childNode); + }); +} + function getDtsFiles(libDir: string): string[] { let dtsFiles:string[] = []; function finDtsFile(dir){ -- Gitee From 7884ba613972fec5c3b8d7429ba2b11c4e82444f Mon Sep 17 00:00:00 2001 From: zhangchen168 Date: Mon, 10 Oct 2022 10:37:16 +0800 Subject: [PATCH 14/59] Support the function overload with export keyword Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5URVH Test: Test262,es2abc regression,es2abc tsc. Signed-off-by: zhangchen168 Change-Id: I6df372288bae85918b25193e44fa72e841b3816a --- es2panda/parser/statementParser.cpp | 5 + ...test_export-function-overload-expected.txt | 401 ++++++++++++++++++ .../ts/test_export-function-overload.ts | 20 + es2panda/test/test_tsc_ignore_list.txt | 1 - 4 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 es2panda/test/parser/ts/test_export-function-overload-expected.txt create mode 100644 es2panda/test/parser/ts/test_export-function-overload.ts diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index fb0b61b1f8..c1bb9523d0 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -2225,6 +2225,10 @@ void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isT ThrowSyntaxError("A class or function declaration without the default modifier mush have a name.", declNode->Start()); } + if (declNode->IsFunctionDeclaration() && + declNode->AsFunctionDeclaration()->Function()->IsOverload()) { + return; + } if (isTsModule) { tsModuleScope->AddExportVariable(name->Name()); } else { @@ -2404,6 +2408,7 @@ ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer: VariableParsingFlags flag = isTsModule ? VariableParsingFlags::NO_OPTS : VariableParsingFlags::EXPORTED; ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED; + switch (lexer_->GetToken().Type()) { case lexer::TokenType::KEYW_VAR: { decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare); diff --git a/es2panda/test/parser/ts/test_export-function-overload-expected.txt b/es2panda/test/parser/ts/test_export-function-overload-expected.txt new file mode 100644 index 0000000000..339bb2c0ae --- /dev/null +++ b/es2panda/test/parser/ts/test_export-function-overload-expected.txt @@ -0,0 +1,401 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "TSDeclareFunction", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "func", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 25 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "TSStringKeyword", + "loc": { + "start": { + "line": 17, + "column": 36 + }, + "end": { + "line": 17, + "column": 42 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSAnyKeyword", + "loc": { + "start": { + "line": 17, + "column": 53 + }, + "end": { + "line": 17, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 53 + }, + "end": { + "line": 17, + "column": 58 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 47 + }, + "end": { + "line": 17, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 44 + }, + "end": { + "line": 17, + "column": 51 + } + } + } + ], + "returnType": { + "type": "TSVoidKeyword", + "loc": { + "start": { + "line": 17, + "column": 61 + }, + "end": { + "line": 17, + "column": 65 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 66 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 66 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 66 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "func", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "TSStringKeyword", + "loc": { + "start": { + "line": 18, + "column": 36 + }, + "end": { + "line": 18, + "column": 42 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 34 + } + } + } + ], + "returnType": { + "type": "TSAnyKeyword", + "loc": { + "start": { + "line": 18, + "column": 45 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 13 + } + } + }, + "right": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 49 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 8 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 8 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/ts/test_export-function-overload.ts b/es2panda/test/parser/ts/test_export-function-overload.ts new file mode 100644 index 0000000000..593f76bc07 --- /dev/null +++ b/es2panda/test/parser/ts/test_export-function-overload.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export function func(a: number, b: string, ...args: any[]): void; +export function func(a: number, b: string): any { + return a + b; +} \ No newline at end of file diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..52ee428e17 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -52,7 +52,6 @@ es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringFo es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/systemNamespaceAliasEmit.ts es2panda/test/TypeScript/tests/cases/compiler/taggedTemplateStringWithSymbolExpression01.ts -es2panda/test/TypeScript/tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts es2panda/test/TypeScript/tests/cases/compiler/withStatementInternalComments.ts es2panda/test/TypeScript/tests/cases/conformance/async/es2017/asyncAwait_es2017.ts es2panda/test/TypeScript/tests/cases/conformance/classes/members/privateNames/privateNameComputedPropertyName1.ts -- Gitee From 66f3bbe9e10f277e04db0db0610eff5abd757d27 Mon Sep 17 00:00:00 2001 From: zhangchen168 Date: Tue, 11 Oct 2022 17:31:17 +0800 Subject: [PATCH 15/59] Support the ExportNamedDeclaration in declare namespace Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5V59F Test: test262,es2abc regression,es2abc tsc. Signed-off-by: zhangchen168 Change-Id: I7c9c3403d65caab66709f7540756e75a3696ac88 --- es2panda/binder/binder.cpp | 19 +- es2panda/parser/statementParser.cpp | 5 + ...aration-named-namespace-error-expected.txt | 1 + ...xport-declaration-named-namespace-error.ts | 21 + ...t-declaration-named-namespace-expected.txt | 844 ++++++++++++++++++ ...test_export-declaration-named-namespace.ts | 40 + es2panda/test/test_tsc_ignore_list.txt | 5 +- 7 files changed, 929 insertions(+), 6 deletions(-) create mode 100644 es2panda/test/parser/ts/test_export-declaration-named-namespace-error-expected.txt create mode 100644 es2panda/test/parser/ts/test_export-declaration-named-namespace-error.ts create mode 100644 es2panda/test/parser/ts/test_export-declaration-named-namespace-expected.txt create mode 100644 es2panda/test/parser/ts/test_export-declaration-named-namespace.ts diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 1c6f0022a7..6ad17db5ea 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -127,10 +127,25 @@ void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl) ASSERT(topScope_->IsModuleScope()); for (auto *it : exportDecl->Specifiers()) { auto localName = it->AsExportSpecifier()->Local()->Name(); - if (topScope_->FindLocal(localName) == nullptr) { + if (scope_->IsTSModuleScope()) { + if (scope_->FindLocal(localName, ResolveBindingOptions::ALL) == nullptr && + !scope_->InLocalTSBindings(localName) && + !scope_->AsTSModuleScope()->InExportBindings(localName)) { + ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName); + } + continue; + } + ASSERT(topScope_ == scope_); + if (scope_->FindLocal(localName) == nullptr) { + // The declaration of ts cannot correspond to the variables of ts before transform, + // After the transform, they are all js variables. So it can return directly here. + if (scope_->InLocalTSBindings(localName) || + scope_->FindLocal(localName, ResolveBindingOptions::INTERFACES)) { + continue; + } ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName); } - topScope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName); + scope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName); } } diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index fb0b61b1f8..3cdfe5cb92 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -2095,6 +2095,11 @@ void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source, const Arena void ParserImpl::AddExportNamedEntryItem(const ArenaVector &specifiers, const ir::StringLiteral *source) { + // The exported objects in the TSModuleScope do not need to be allocated index. + if (context_.IsTsModule()) { + ASSERT(Binder()->GetScope()->IsTSModuleScope()); + return; + } auto moduleRecord = GetSourceTextModuleRecord(); ASSERT(moduleRecord != nullptr); if (source) { diff --git a/es2panda/test/parser/ts/test_export-declaration-named-namespace-error-expected.txt b/es2panda/test/parser/ts/test_export-declaration-named-namespace-error-expected.txt new file mode 100644 index 0000000000..d7d356f8fe --- /dev/null +++ b/es2panda/test/parser/ts/test_export-declaration-named-namespace-error-expected.txt @@ -0,0 +1 @@ +SyntaxError: Export name '_func' is not defined. [test_export-declaration-named-namespace-error.ts:18:14] diff --git a/es2panda/test/parser/ts/test_export-declaration-named-namespace-error.ts b/es2panda/test/parser/ts/test_export-declaration-named-namespace-error.ts new file mode 100644 index 0000000000..0e0e3aca69 --- /dev/null +++ b/es2panda/test/parser/ts/test_export-declaration-named-namespace-error.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +declare namespace ns { + export { _func as try }; +} + +ns.try(() => { }); \ No newline at end of file diff --git a/es2panda/test/parser/ts/test_export-declaration-named-namespace-expected.txt b/es2panda/test/parser/ts/test_export-declaration-named-namespace-expected.txt new file mode 100644 index 0000000000..b6280a1055 --- /dev/null +++ b/es2panda/test/parser/ts/test_export-declaration-named-namespace-expected.txt @@ -0,0 +1,844 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "TSDeclareFunction", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_func", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "Function", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSAnyKeyword", + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 47 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 36 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 40 + } + } + } + ], + "returnType": { + "type": "TSAnyKeyword", + "loc": { + "start": { + "line": 18, + "column": 50 + }, + "end": { + "line": 18, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 54 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "_func", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "exported": { + "type": "Identifier", + "name": "try", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "declare": true, + "global": false, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 22, + "column": 3 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "ns", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 3 + } + } + }, + "property": { + "type": "Identifier", + "name": "try", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 4 + }, + "end": { + "line": 22, + "column": 7 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 7 + } + } + }, + "arguments": [ + { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 8 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 8 + }, + "end": { + "line": 22, + "column": 17 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 19 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns1", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 19 + }, + "end": { + "line": 24, + "column": 22 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "TSEnumDeclaration", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 10 + }, + "end": { + "line": 25, + "column": 11 + } + } + }, + "members": [], + "const": false, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 14 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "exported": { + "type": "Identifier", + "name": "enum1", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 19 + }, + "end": { + "line": 26, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 27 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 23 + }, + "end": { + "line": 27, + "column": 2 + } + } + }, + "declare": true, + "global": false, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 29, + "column": 8 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "nullns", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 19 + }, + "end": { + "line": 29, + "column": 25 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [], + "loc": { + "start": { + "line": 29, + "column": 25 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "declare": true, + "global": false, + "loc": { + "start": { + "line": 29, + "column": 9 + }, + "end": { + "line": 32, + "column": 7 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "nullns", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 10 + }, + "end": { + "line": 32, + "column": 16 + } + } + }, + "exported": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 20 + }, + "end": { + "line": 32, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 10 + }, + "end": { + "line": 32, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 1 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns2", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 19 + }, + "end": { + "line": 34, + "column": 22 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 16 + }, + "end": { + "line": 35, + "column": 17 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 35, + "column": 16 + }, + "end": { + "line": 35, + "column": 17 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 35, + "column": 12 + }, + "end": { + "line": 35, + "column": 18 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 34, + "column": 23 + }, + "end": { + "line": 36, + "column": 2 + } + } + }, + "declare": true, + "global": false, + "loc": { + "start": { + "line": 34, + "column": 9 + }, + "end": { + "line": 38, + "column": 8 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns2", + "decorators": [], + "loc": { + "start": { + "line": 38, + "column": 19 + }, + "end": { + "line": 38, + "column": 22 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 13 + }, + "end": { + "line": 39, + "column": 14 + } + } + }, + "exported": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 18 + }, + "end": { + "line": 39, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 39, + "column": 13 + }, + "end": { + "line": 39, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 39, + "column": 5 + }, + "end": { + "line": 39, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 38, + "column": 23 + }, + "end": { + "line": 40, + "column": 2 + } + } + }, + "declare": true, + "global": false, + "loc": { + "start": { + "line": 38, + "column": 9 + }, + "end": { + "line": 40, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 40, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/ts/test_export-declaration-named-namespace.ts b/es2panda/test/parser/ts/test_export-declaration-named-namespace.ts new file mode 100644 index 0000000000..41e091d2ad --- /dev/null +++ b/es2panda/test/parser/ts/test_export-declaration-named-namespace.ts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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. + */ + + +declare namespace ns { + function _func(p: Function, ...args: any[]): any; + export { _func as try }; +} + +ns.try(() => { }); + +declare namespace ns1 { + enum a {} + export { a as enum1 }; +} + +declare namespace nullns{ + +} +export { nullns as foo } + +declare namespace ns2 { + export var a; +} + +declare namespace ns2 { + export {a as b} +} \ No newline at end of file diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..f2fa135d83 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -18,10 +18,7 @@ es2panda/test/TypeScript/tests/cases/compiler/elidedEmbeddedStatementsReplacedWi es2panda/test/TypeScript/tests/cases/compiler/emitBundleWithShebang1.ts es2panda/test/TypeScript/tests/cases/compiler/emitDecoratorMetadata_restArgs.ts es2panda/test/TypeScript/tests/cases/compiler/exportAsNamespace.d.ts -es2panda/test/TypeScript/tests/cases/compiler/exportDeclarationsInAmbientNamespaces.ts -es2panda/test/TypeScript/tests/cases/compiler/exportEqualsOfModule.ts es2panda/test/TypeScript/tests/cases/compiler/exportRedeclarationTypeAliases.ts -es2panda/test/TypeScript/tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts es2panda/test/TypeScript/tests/cases/compiler/fileWithNextLine2.ts es2panda/test/TypeScript/tests/cases/compiler/genericRecursiveImplicitConstructorErrors2.ts es2panda/test/TypeScript/tests/cases/compiler/getterSetterNonAccessor.ts @@ -29,6 +26,7 @@ es2panda/test/TypeScript/tests/cases/compiler/globalIsContextualKeyword.ts es2panda/test/TypeScript/tests/cases/compiler/implementsInClassExpression.ts es2panda/test/TypeScript/tests/cases/compiler/inferenceErasedSignatures.ts es2panda/test/TypeScript/tests/cases/compiler/isLiteral1.ts +es2panda/test/TypeScript/tests/cases/compiler/noCircularDefinitionOnExportOfPrivateInMergedNamespace.ts es2panda/test/TypeScript/tests/cases/compiler/isLiteral2.ts es2panda/test/TypeScript/tests/cases/compiler/letAsIdentifier2.ts es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForIn_ES5.ts @@ -50,7 +48,6 @@ es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringFo es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPattern2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPatternDefaultValues2.ts -es2panda/test/TypeScript/tests/cases/compiler/systemNamespaceAliasEmit.ts es2panda/test/TypeScript/tests/cases/compiler/taggedTemplateStringWithSymbolExpression01.ts es2panda/test/TypeScript/tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts es2panda/test/TypeScript/tests/cases/compiler/withStatementInternalComments.ts -- Gitee From cf11c4658097ce06de28bf60931351c6100897be Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Mon, 24 Oct 2022 16:11:14 +0800 Subject: [PATCH 16/59] Fix testinstype test Issue: I5XDVD Signed-off-by: gavin1012_hw Change-Id: I48ca1bc2ccf9861cb18fed841a33e5d794c6fe4e --- testTs/instype/recordthis-expected.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testTs/instype/recordthis-expected.txt b/testTs/instype/recordthis-expected.txt index d1e0c46c2d..fbc6352221 100644 --- a/testTs/instype/recordthis-expected.txt +++ b/testTs/instype/recordthis-expected.txt @@ -9,7 +9,7 @@ Handle types for function: setName Handle types for function: setId (instruction order, type): (-2, 111), (-1, 105), Handle types for function: dump -(instruction order, type): (-2, 111), (-1, 107), (14, 4), +(instruction order, type): (-2, 111), (-1, 107), (16, 4), Handle types for function: stest (instruction order, type): (-2, 101), (-1, 108), Handle types for function: test @@ -17,6 +17,6 @@ Handle types for function: test Handle types for function: testwiththis (instruction order, type): (-2, 111), (-1, 110), Handle types for function: add -(instruction order, type): (-1, 112), (7, 1), +(instruction order, type): (-1, 112), (9, 1), Handle types for function: func_main_0 (instruction order, type): -- Gitee From 47a9afebaa4b871282f9f7ef91f55aa1bfd3b74e Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 24 Oct 2022 23:55:56 +0800 Subject: [PATCH 17/59] Descriptor: Fix standalone build error Details: Modify gn and some template Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5XGZ4 Signed-off-by: wengchangcheng Change-Id: I1437984773e9bb0a6c849a4026653891fde769c1 --- es2panda/BUILD.gn | 3 +-- es2panda/es2abc_config.gni | 9 +-------- es2panda/test/BUILD.gn | 1 - ets_frontend_config.gni | 16 ++++++++++++---- merge_abc/BUILD.gn | 10 ++++------ ts2panda/BUILD.gn | 2 -- ts2panda/ts2abc/BUILD.gn | 20 +++++--------------- ts2panda/ts2abc_config.gni | 3 ++- 8 files changed, 25 insertions(+), 39 deletions(-) diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 27fea7ea42..86804569e5 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -13,7 +13,6 @@ import("//arkcompiler/ets_frontend/ets_frontend_config.gni") import("//arkcompiler/runtime_core/ark_config.gni") -import("//build/ohos.gni") es2panda_src = [ "es2panda.cpp", @@ -395,7 +394,7 @@ ohos_static_library("es2panda_lib") { "$ark_root/libpandabase:libarkbase_frontend_static", "$ark_root/libpandafile:libarkfile_frontend_static", "$ark_root/libziparchive:libarkziparchive_frontend_static", - "//third_party/icu/icu4c:static_icuuc", + "$ark_third_party_root/icu/icu4c:static_icuuc", ] if (enable_bytecode_optimizer) { diff --git a/es2panda/es2abc_config.gni b/es2panda/es2abc_config.gni index 5c1786c68a..c46973d596 100644 --- a/es2panda/es2abc_config.gni +++ b/es2panda/es2abc_config.gni @@ -12,15 +12,8 @@ # limitations under the License. import("//arkcompiler/ets_frontend/ets_frontend_config.gni") -if (defined(ark_independent_build)) { - import("$build_root/ark.gni") - es2abc_root = "//ets_frontend/es2panda" -} else { - import("//build/ohos.gni") - build_root = "//build" - es2abc_root = "//arkcompiler/ets_frontend/es2panda" -} +es2abc_root = "//arkcompiler/ets_frontend/es2panda" es2abc_build_path = "" es2abc_build_deps = "" es2abc_out_root = "" diff --git a/es2panda/test/BUILD.gn b/es2panda/test/BUILD.gn index e3753c2c8e..b8c6c5c20e 100644 --- a/es2panda/test/BUILD.gn +++ b/es2panda/test/BUILD.gn @@ -13,7 +13,6 @@ import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//build/ohos.gni") action("es2abc_parser_tests") { script = "${es2abc_root}/test/runner.py" diff --git a/ets_frontend_config.gni b/ets_frontend_config.gni index b4a3c1928a..f09625004a 100644 --- a/ets_frontend_config.gni +++ b/ets_frontend_config.gni @@ -11,13 +11,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -if (defined(ark_independent_build)) { - ets_frontend_root = "//ets_frontend" -} else { +if (!defined(ark_standalone_build)) { + ark_standalone_build = false +} + +if (!ark_standalone_build) { build_root = "//build" - ets_frontend_root = "//arkcompiler/ets_frontend" + ark_third_party_root = "//third_party" + import("$build_root/ohos.gni") +} else { + ark_third_party_root = "//arkcompiler/toolchain/build/third_party_gn" + import("$build_root/ark.gni") } +ets_frontend_root = "//arkcompiler/ets_frontend" + toolchain_linux = "$build_root/toolchain/linux:clang_x64" if (host_cpu == "arm64") { toolchain_mac = "$build_root/toolchain/mac:clang_arm64" diff --git a/merge_abc/BUILD.gn b/merge_abc/BUILD.gn index 3b928ff1c4..be0d3d7297 100644 --- a/merge_abc/BUILD.gn +++ b/merge_abc/BUILD.gn @@ -13,8 +13,6 @@ import("//arkcompiler/ets_frontend/ets_frontend_config.gni") import("//arkcompiler/runtime_core/ark_config.gni") -import("//build/config/clang/clang.gni") -import("//build/ohos.gni") import("//developtools/profiler/build/config.gni") proto_base_dir = "protos" @@ -106,7 +104,7 @@ host_protoc_path = root_out_dir + host_out_path + "/" + protoc_binary_out_path + "/protoc" action("arkcompiler_generate_proto") { - deps = [ "//third_party/protobuf:protoc($host_toolchain)" ] + deps = [ "$ark_third_party_root/protobuf:protoc($host_toolchain)" ] args = [] sources = [] outputs = proto_generated_header + proto_generated_source @@ -137,8 +135,8 @@ ohos_source_set("assembly_proto_static") { deps = [ ":arkcompiler_generate_proto", - "//third_party/protobuf:protobuf_lite_static", - "//third_party/protobuf:protobuf_static", + "$ark_third_party_root/protobuf:protobuf_lite_static", + "$ark_third_party_root/protobuf:protobuf_static", ] sources = proto_generated_header + proto_generated_source + @@ -176,7 +174,7 @@ ohos_executable("merge_abc") { "$ark_root/libpandabase:libarkbase_frontend_static", "$ark_root/libpandafile:libarkfile_frontend_static", "$ark_root/libziparchive:libarkziparchive_frontend_static", - "//third_party/icu/icu4c:static_icuuc", + "$ark_third_party_root/icu/icu4c:static_icuuc", ] ldflags = [] diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index d1ef4ebfd5..c5f498c329 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -13,8 +13,6 @@ import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") import("//arkcompiler/runtime_core/ark_config.gni") -import("//build/config/clang/clang.gni") -import("//build/ohos.gni") src_dir = target_out_dir + "/src" src_dir_full_path = rebase_path("${ts2abc_root}/src") diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 5653deaadf..19f7bc1a7b 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -11,13 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -if (!defined(ark_independent_build)) { - import("//arkcompiler/runtime_core/ark_config.gni") - import("//build/ohos.gni") -} else { - import("//runtime_core/ark_config.gni") - import("$build_root/ark.gni") -} +import("//arkcompiler/runtime_core/ark_config.gni") jsoncpp_root = "$ark_third_party_root/jsoncpp" @@ -57,9 +51,9 @@ config("flag_config") { source_set("jsoncpp_set_static") { sources = [ - "$ark_third_party_root/jsoncpp/src/lib_json/json_reader.cpp", - "$ark_third_party_root/jsoncpp/src/lib_json/json_value.cpp", - "$ark_third_party_root/jsoncpp/src/lib_json/json_writer.cpp", + "//third_party/jsoncpp/src/lib_json/json_reader.cpp", + "//third_party/jsoncpp/src/lib_json/json_value.cpp", + "//third_party/jsoncpp/src/lib_json/json_writer.cpp", ] public_configs = [ "$jsoncpp_root:jsoncpp_config" ] public_configs += [ ":flag_config" ] @@ -69,7 +63,7 @@ source_set("jsoncpp_set_static") { ] } -if (!defined(ark_independent_build)) { +if (!ark_standalone_build) { ohos_static_library("jsoncpp_static") { deps = [ ":jsoncpp_set_static" ] use_exceptions = true @@ -139,8 +133,4 @@ if (!defined(ark_independent_build)) { part_name = "ets_frontend" subsystem_name = "arkcompiler" } -} else { - ark_static_library("jsoncpp_static") { - deps = [ ":jsoncpp_set_static" ] - } } diff --git a/ts2panda/ts2abc_config.gni b/ts2panda/ts2abc_config.gni index 01d9002487..b1c7f692eb 100755 --- a/ts2panda/ts2abc_config.gni +++ b/ts2panda/ts2abc_config.gni @@ -10,8 +10,9 @@ # 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("//arkcompiler/ets_frontend/ets_frontend_config.gni") -if (!defined(ark_independent_build)) { +if (!ark_standalone_build) { import("//build/ohos.gni") import("//build/test.gni") build_root = "//build" -- Gitee From 2abb503074ff5eb5fdb1688ca75fb15c5ef3fc94 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Fri, 16 Sep 2022 20:35:23 +0800 Subject: [PATCH 18/59] Enable decorator and some ts class feature in es2abc Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5U2KR Test: test262, parser tests, compiler tests Signed-off-by: xucheng46 Change-Id: Ia5a7c354c5956478a7411083d74b4ede9be98dbf --- es2panda/binder/scope.h | 9 +- es2panda/compiler/core/function.cpp | 10 +- es2panda/ir/base/classProperty.h | 25 + es2panda/ir/base/decorator.h | 5 + es2panda/ir/base/methodDefinition.cpp | 5 + es2panda/ir/base/methodDefinition.h | 36 +- es2panda/ir/base/scriptFunction.h | 5 + es2panda/ir/expressions/classExpression.h | 5 + es2panda/ir/expressions/functionExpression.h | 5 + es2panda/ir/expressions/identifier.h | 6 + .../ir/expressions/literals/bigIntLiteral.h | 5 + es2panda/ir/statements/blockStatement.cpp | 5 + es2panda/ir/statements/blockStatement.h | 2 + es2panda/ir/statements/classDeclaration.h | 11 + es2panda/ir/statements/expressionStatement.h | 5 + es2panda/ir/ts/tsModuleBlock.cpp | 5 + es2panda/ir/ts/tsModuleBlock.h | 2 + es2panda/ir/ts/tsParameterProperty.cpp | 5 +- es2panda/ir/ts/tsParameterProperty.h | 2 +- es2panda/ir/ts/tsPrivateIdentifier.h | 5 + es2panda/parser/expressionParser.cpp | 15 +- es2panda/parser/parserImpl.cpp | 30 +- es2panda/parser/parserImpl.h | 8 +- es2panda/parser/transformer/transformer.cpp | 763 ++++++++++++++++-- es2panda/parser/transformer/transformer.h | 114 ++- .../classes/test-ts-classes-1-expected.txt | 2 + .../conformance/classes/test-ts-classes-1.ts | 26 + .../classes/test-ts-classes-2-expected.txt | 2 + .../conformance/classes/test-ts-classes-2.ts | 25 + .../classes/test-ts-classes-3-expected.txt | 2 + .../conformance/classes/test-ts-classes-3.ts | 27 + .../classes/test-ts-classes-4-expected.txt | 1 + .../conformance/classes/test-ts-classes-4.ts | 21 + .../classes/test-ts-classes-5-expected.txt | 1 + .../conformance/classes/test-ts-classes-5.ts | 22 + .../classes/test-ts-classes-6-expected.txt | 1 + .../conformance/classes/test-ts-classes-6.ts | 21 + .../classes/test-ts-classes-7-expected.txt | 1 + .../conformance/classes/test-ts-classes-7.ts | 20 + .../classes/test-ts-classes-8-expected.txt | 1 + .../conformance/classes/test-ts-classes-8.ts | 25 + .../test-ts-decorators-1-expected.txt | 1 + .../decorators/test-ts-decorators-1.ts | 22 + .../test-ts-decorators-10-expected.txt | 4 + .../decorators/test-ts-decorators-10.ts | 34 + .../test-ts-decorators-11-expected.txt | 2 + .../decorators/test-ts-decorators-11.ts | 27 + .../test-ts-decorators-12-expected.txt | 2 + .../decorators/test-ts-decorators-12.ts | 34 + .../test-ts-decorators-13-expected.txt | 4 + .../decorators/test-ts-decorators-13.ts | 34 + .../test-ts-decorators-2-expected.txt | 3 + .../decorators/test-ts-decorators-2.ts | 29 + .../test-ts-decorators-3-expected.txt | 10 + .../decorators/test-ts-decorators-3.ts | 37 + .../test-ts-decorators-4-expected.txt | 3 + .../decorators/test-ts-decorators-4.ts | 28 + .../test-ts-decorators-5-expected.txt | 21 + .../decorators/test-ts-decorators-5.ts | 29 + .../test-ts-decorators-6-expected.txt | 1 + .../decorators/test-ts-decorators-6.ts | 30 + .../test-ts-decorators-7-expected.txt | 18 + .../decorators/test-ts-decorators-7.ts | 81 ++ .../test-ts-decorators-8-expected.txt | 3 + .../decorators/test-ts-decorators-8.ts | 32 + .../test-ts-decorators-9-expected.txt | 1 + .../decorators/test-ts-decorators-9.ts | 24 + .../parser/ts/test_decorator-expected.txt | 33 +- es2panda/test/runner.py | 10 +- es2panda/test/test_tsc_ignore_list.txt | 1 - 70 files changed, 1733 insertions(+), 111 deletions(-) create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 70be5ce9a7..3fd392aef7 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -258,7 +258,12 @@ public: return node_; } - void BindNode(const ir::AstNode *node) + ir::AstNode *Node() + { + return node_; + } + + void BindNode(ir::AstNode *node) { node_ = node; } @@ -358,7 +363,7 @@ protected: ArenaVector decls_; VariableMap bindings_; TSBindings tsBindings_; - const ir::AstNode *node_ {}; + ir::AstNode *node_ {}; const compiler::IRNode *startIns_ {}; const compiler::IRNode *endIns_ {}; }; diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index b9a4bce84f..80bd914fa0 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace panda::es2panda::compiler { @@ -58,7 +59,11 @@ static void CompileFunctionParameterDeclaration(PandaGen *pg, const ir::ScriptFu uint32_t index = 0; - for (const auto *param : func->Params()) { + for (const auto *it : func->Params()) { + auto *param = it; + if (param->IsTSParameterProperty()) { + param = param->AsTSParameterProperty()->Parameter(); + } LReference ref = LReference::CreateLRef(pg, param, true); [[maybe_unused]] binder::Variable *paramVar = ref.Variable(); @@ -124,6 +129,9 @@ static void CompileInstanceFields(PandaGen *pg, const ir::ScriptFunction *decl) for (auto const &stmt : statements) { if (stmt->IsClassProperty()) { const auto *prop = stmt->AsClassProperty(); + if (prop->IsStatic()) { + continue; + } if (!prop->Value()) { pg->LoadConst(stmt, Constant::JS_UNDEFINED); } else { diff --git a/es2panda/ir/base/classProperty.h b/es2panda/ir/base/classProperty.h index 2380eea356..b2cc33c8d7 100644 --- a/es2panda/ir/base/classProperty.h +++ b/es2panda/ir/base/classProperty.h @@ -51,11 +51,26 @@ public: return key_; } + Expression *Key() + { + return key_; + } + + void SetKey(Expression *key) + { + key_ = key; + } + const Expression *Value() const { return value_; } + Expression *Value() + { + return value_; + } + const Expression *TypeAnnotation() const { return typeAnnotation_; @@ -66,11 +81,21 @@ public: return modifiers_; } + bool IsStatic() const + { + return (modifiers_ & ModifierFlags::STATIC) != 0; + } + const ArenaVector &Decorators() const { return decorators_; } + bool HasDecorators() const + { + return !decorators_.empty(); + } + bool IsComputed() const { return isComputed_; diff --git a/es2panda/ir/base/decorator.h b/es2panda/ir/base/decorator.h index 8ea87b4b04..6c6f2410f2 100644 --- a/es2panda/ir/base/decorator.h +++ b/es2panda/ir/base/decorator.h @@ -39,6 +39,11 @@ public: return expr_; } + Expression *Expr() + { + return expr_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/base/methodDefinition.cpp b/es2panda/ir/base/methodDefinition.cpp index 4c814e6eac..3975b528ca 100644 --- a/es2panda/ir/base/methodDefinition.cpp +++ b/es2panda/ir/base/methodDefinition.cpp @@ -30,6 +30,11 @@ const ScriptFunction *MethodDefinition::Function() const return value_->Function(); } +ScriptFunction *MethodDefinition::Function() +{ + return value_->Function(); +} + void MethodDefinition::Iterate(const NodeTraverser &cb) const { cb(key_); diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index 77c5fc8c29..ff51e020bf 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -34,11 +34,16 @@ class FunctionExpression; enum class MethodDefinitionKind { CONSTRUCTOR, METHOD, GET, SET }; +struct ParamDecorators { + size_t paramIndex; + ArenaVector decorators; +}; + class MethodDefinition : public Statement { public: explicit MethodDefinition(MethodDefinitionKind kind, Expression *key, FunctionExpression *value, ModifierFlags modifiers, ArenaAllocator *allocator, ArenaVector &&decorators, - bool isComputed) + ArenaVector &¶mDecorators, bool isComputed) : Statement(AstNodeType::METHOD_DEFINITION), kind_(kind), key_(key), @@ -46,6 +51,7 @@ public: modifiers_(modifiers), overloads_(allocator->Adapter()), decorators_(std::move(decorators)), + paramDecorators_(std::move(paramDecorators)), isComputed_(isComputed) { } @@ -65,6 +71,16 @@ public: return key_; } + Expression *Key() + { + return key_; + } + + void SetKey(Expression *key) + { + key_ = key; + } + const FunctionExpression *Value() const { return value_; @@ -100,6 +116,21 @@ public: return decorators_; } + const ArenaVector &GetParamDecorators() const + { + return paramDecorators_; + } + + bool HasParamDecorators() const + { + return !paramDecorators_.empty(); + } + + bool HasDecorators() const + { + return !decorators_.empty(); + } + void SetOverloads(ArenaVector &&overloads) { overloads_ = std::move(overloads); @@ -112,6 +143,8 @@ public: const ScriptFunction *Function() const; + ScriptFunction *Function(); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; @@ -125,6 +158,7 @@ private: ModifierFlags modifiers_; ArenaVector overloads_; ArenaVector decorators_; + ArenaVector paramDecorators_; bool isComputed_; }; diff --git a/es2panda/ir/base/scriptFunction.h b/es2panda/ir/base/scriptFunction.h index aaf29adb90..9d73b8121c 100644 --- a/es2panda/ir/base/scriptFunction.h +++ b/es2panda/ir/base/scriptFunction.h @@ -139,6 +139,11 @@ public: return (flags_ & ir::ScriptFunctionFlags::METHOD) != 0; } + bool FunctionBodyIsExpression() const + { + return (flags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0; + } + bool Declare() const { return declare_; diff --git a/es2panda/ir/expressions/classExpression.h b/es2panda/ir/expressions/classExpression.h index b4f350b3ee..e20a464161 100644 --- a/es2panda/ir/expressions/classExpression.h +++ b/es2panda/ir/expressions/classExpression.h @@ -40,6 +40,11 @@ public: return def_; } + ClassDefinition *Definition() + { + return def_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/expressions/functionExpression.h b/es2panda/ir/expressions/functionExpression.h index 3211855b98..227e630b9f 100644 --- a/es2panda/ir/expressions/functionExpression.h +++ b/es2panda/ir/expressions/functionExpression.h @@ -40,6 +40,11 @@ public: return func_; } + ScriptFunction *Function() + { + return func_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/expressions/identifier.h b/es2panda/ir/expressions/identifier.h index 543397f6c6..1055ba458d 100644 --- a/es2panda/ir/expressions/identifier.h +++ b/es2panda/ir/expressions/identifier.h @@ -78,6 +78,11 @@ public: return name_; } + void SetName(util::StringView name) + { + name_ = name; + } + const ArenaVector &Decorators() const { return decorators_; @@ -132,6 +137,7 @@ private: util::StringView name_; Expression *typeAnnotation_ {}; IdentifierFlags flags_ {IdentifierFlags::NONE}; + // TODO(xucheng): remove the decorators in identifier ArenaVector decorators_; }; diff --git a/es2panda/ir/expressions/literals/bigIntLiteral.h b/es2panda/ir/expressions/literals/bigIntLiteral.h index ef1aee885f..70290e3c4b 100644 --- a/es2panda/ir/expressions/literals/bigIntLiteral.h +++ b/es2panda/ir/expressions/literals/bigIntLiteral.h @@ -39,6 +39,11 @@ public: return src_; } + util::StringView Str() + { + return src_; + } + LiteralTag Tag() const override { return LiteralTag::NULL_VALUE; diff --git a/es2panda/ir/statements/blockStatement.cpp b/es2panda/ir/statements/blockStatement.cpp index 24abd03273..39bff4eff1 100644 --- a/es2panda/ir/statements/blockStatement.cpp +++ b/es2panda/ir/statements/blockStatement.cpp @@ -82,4 +82,9 @@ void BlockStatement::UpdateSelf(const NodeUpdater &cb, binder::Binder *binder) } } +void BlockStatement::AddStatementInFront(Statement *statement) +{ + statements_.insert(statements_.begin(), statement); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/statements/blockStatement.h b/es2panda/ir/statements/blockStatement.h index 3769fd6862..c9225bfdac 100644 --- a/es2panda/ir/statements/blockStatement.h +++ b/es2panda/ir/statements/blockStatement.h @@ -50,6 +50,8 @@ public: return statements_; } + void AddStatementInFront(Statement *statement); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/statements/classDeclaration.h b/es2panda/ir/statements/classDeclaration.h index 5f2864fa1c..f13b0708e3 100644 --- a/es2panda/ir/statements/classDeclaration.h +++ b/es2panda/ir/statements/classDeclaration.h @@ -41,10 +41,21 @@ public: return def_; } + ClassDefinition *Definition() + { + return def_; + } + const ArenaVector &Decorators() const { return decorators_; } + + bool HasDecorators() const + { + return !decorators_.empty(); + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/statements/expressionStatement.h b/es2panda/ir/statements/expressionStatement.h index 36b2d2cf9d..1e2fa27caf 100644 --- a/es2panda/ir/statements/expressionStatement.h +++ b/es2panda/ir/statements/expressionStatement.h @@ -40,6 +40,11 @@ public: return expression_; } + Expression *GetExpression() + { + return expression_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/ts/tsModuleBlock.cpp b/es2panda/ir/ts/tsModuleBlock.cpp index 8955fc3b40..1ffe23e4e4 100644 --- a/es2panda/ir/ts/tsModuleBlock.cpp +++ b/es2panda/ir/ts/tsModuleBlock.cpp @@ -64,4 +64,9 @@ void TSModuleBlock::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::B } } +void TSModuleBlock::AddStatementInFront(Statement *statement) +{ + statements_.insert(statements_.begin(), statement); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/ts/tsModuleBlock.h b/es2panda/ir/ts/tsModuleBlock.h index f62792938f..48babf52c8 100644 --- a/es2panda/ir/ts/tsModuleBlock.h +++ b/es2panda/ir/ts/tsModuleBlock.h @@ -46,6 +46,8 @@ public: return statements_; } + void AddStatementInFront(Statement *statement); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/ts/tsParameterProperty.cpp b/es2panda/ir/ts/tsParameterProperty.cpp index 2768a1e419..f1a33df64b 100644 --- a/es2panda/ir/ts/tsParameterProperty.cpp +++ b/es2panda/ir/ts/tsParameterProperty.cpp @@ -39,7 +39,10 @@ void TSParameterProperty::Dump(ir::AstDumper *dumper) const {"parameter", parameter_}}); } -void TSParameterProperty::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSParameterProperty::Compile(compiler::PandaGen *pg) const +{ + parameter_->Compile(pg); +} checker::Type *TSParameterProperty::Check([[maybe_unused]] checker::Checker *checker) const { diff --git a/es2panda/ir/ts/tsParameterProperty.h b/es2panda/ir/ts/tsParameterProperty.h index 4e655d76af..9d351d9e41 100644 --- a/es2panda/ir/ts/tsParameterProperty.h +++ b/es2panda/ir/ts/tsParameterProperty.h @@ -76,7 +76,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; diff --git a/es2panda/ir/ts/tsPrivateIdentifier.h b/es2panda/ir/ts/tsPrivateIdentifier.h index 594261e2de..f5d65bbdc8 100644 --- a/es2panda/ir/ts/tsPrivateIdentifier.h +++ b/es2panda/ir/ts/tsPrivateIdentifier.h @@ -41,6 +41,11 @@ public: return key_; } + Expression *Key() + { + return key_; + } + const Expression *Value() const { return value_; diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022..c6051aaeac 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -1729,11 +1729,6 @@ void ParserImpl::ParsePotentialTsFunctionParameter(ExpressionParseFlags flags, i ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault, bool isDeclare) { ir::Expression *returnNode = nullptr; - ArenaVector decorators(Allocator()->Adapter()); - - if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) { - decorators = ParseDecorators(); - } switch (lexer_->GetToken().Type()) { case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { @@ -1754,15 +1749,9 @@ ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool break; } case lexer::TokenType::LITERAL_IDENT: { - returnNode = AllocNode(lexer_->GetToken().Ident(), std::move(decorators)); + returnNode = AllocNode(lexer_->GetToken().Ident(), Allocator()); returnNode->AsIdentifier()->SetReference(); - - if (returnNode->AsIdentifier()->Decorators().empty()) { - returnNode->SetRange(lexer_->GetToken().Loc()); - } else { - returnNode->SetRange( - {returnNode->AsIdentifier()->Decorators().front()->Start(), lexer_->GetToken().End()}); - } + returnNode->SetRange(lexer_->GetToken().Loc()); lexer_->NextToken(); break; } diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 09a79b3c26..112f804ce9 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2271,7 +2271,8 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc, ThrowSyntaxError("Generators are not allowed in an ambient context."); } - ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare); + ArenaVector paramDecorators(Allocator()->Adapter()); + ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, ¶mDecorators); if (func->Body() != nullptr) { lexer_->NextToken(); } @@ -2295,7 +2296,8 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc, *propEnd = func->End(); func->AddFlag(ir::ScriptFunctionFlags::METHOD); auto *method = AllocNode(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(), - std::move(decorators), desc->isComputed); + std::move(decorators), std::move(paramDecorators), + desc->isComputed); method->SetRange(funcExpr->Range()); return method; } @@ -2571,9 +2573,10 @@ ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(bool hasSuperClass, auto *key = AllocNode("constructor", Allocator()); ArenaVector decorators(Allocator()->Adapter()); - + ArenaVector paramDecorators(Allocator()->Adapter()); auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, - ir::ModifierFlags::NONE, Allocator(), std::move(decorators), false); + ir::ModifierFlags::NONE, Allocator(), std::move(decorators), + std::move(paramDecorators), false); return ctor; } @@ -2972,7 +2975,8 @@ void ParserImpl::ValidateFunctionParam(const ArenaVector ¶ } } -ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) +ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare, + ArenaVector *paramDecorators) { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer_->NextToken(); @@ -2980,7 +2984,15 @@ ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) ArenaVector params(Allocator()->Adapter()); bool seenOptional = false; + size_t index = 0; while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) { + auto decorators = ParseDecorators(); + if (!decorators.empty()) { + paramDecorators->push_back({index, std::move(decorators)}); + } + } + ir::Expression *parameter = ParseFunctionParameter(isDeclare); ValidateFunctionParam(params, parameter, &seenOptional); @@ -2994,6 +3006,8 @@ ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { lexer_->NextToken(); } + + index++; } ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); @@ -3183,7 +3197,9 @@ ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation( return typeParamInst; } -ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, bool isDeclare) +ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, + bool isDeclare, + ArenaVector *paramDecorators) { FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET); @@ -3205,7 +3221,7 @@ ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, bool isDec context_.Status() |= ParserStatus::DISALLOW_AWAIT; } - ArenaVector params = ParseFunctionParams(isDeclare); + ArenaVector params = ParseFunctionParams(isDeclare, paramDecorators); ir::Expression *returnTypeAnnotation = nullptr; diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 16d2929ce9..83dee0969d 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -319,14 +320,17 @@ private: ir::TSTypeParameter *ParseTsTypeParameter(bool throwError, bool addBinding = false); ir::TSTypeParameterDeclaration *ParseTsTypeParameterDeclaration(bool throwError = true); ir::TSTypeParameterInstantiation *ParseTsTypeParameterInstantiation(bool throwError = true); - ir::ScriptFunction *ParseFunction(ParserStatus newStatus = ParserStatus::NO_OPTS, bool isDeclare = false); + ir::ScriptFunction *ParseFunction(ParserStatus newStatus = ParserStatus::NO_OPTS, + bool isDeclare = false, + ArenaVector *paramDecorators = nullptr); void ValidateFunctionParam(const ArenaVector ¶ms, const ir::Expression *parameter, bool *seenOptional); void ValidateTsFunctionOverloadParams(const ArenaVector ¶ms); void CheckAccessorPair(const ArenaVector &properties, const ir::Expression *propName, ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator, lexer::SourcePosition errorInfo); - ArenaVector ParseFunctionParams(bool isDeclare = false); + ArenaVector ParseFunctionParams(bool isDeclare = false, + ArenaVector *paramDecorators = nullptr); ir::SpreadElement *ParseSpreadElement(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::TSParameterProperty *CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers); ir::Expression *ParseFunctionParameter(bool isDeclare); diff --git a/es2panda/parser/transformer/transformer.cpp b/es2panda/parser/transformer/transformer.cpp index 463d60e78a..bb0825beea 100644 --- a/es2panda/parser/transformer/transformer.cpp +++ b/es2panda/parser/transformer/transformer.cpp @@ -15,15 +15,26 @@ #include "transformer.h" -#include "ir/base/scriptFunction.h" +#include + #include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/base/decorator.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/scriptFunction.h" #include "ir/expressions/assignmentExpression.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/callExpression.h" +#include "ir/expressions/classExpression.h" #include "ir/expressions/functionExpression.h" #include "ir/expressions/identifier.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/bigIntLiteral.h" #include "ir/expressions/memberExpression.h" #include "ir/expressions/objectExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/thisExpression.h" #include "ir/module/exportNamedDeclaration.h" #include "ir/statements/blockStatement.h" #include "ir/statements/classDeclaration.h" @@ -35,10 +46,11 @@ #include "ir/ts/tsImportEqualsDeclaration.h" #include "ir/ts/tsModuleBlock.h" #include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsPrivateIdentifier.h" #include "ir/ts/tsQualifiedName.h" #include "util/helpers.h" - namespace panda::es2panda::parser { void Transformer::Transform(Program *program) @@ -53,6 +65,7 @@ void Transformer::TransformFromTS() { ASSERT(Extension() == ScriptExtension::TS); VisitTSNodes(program_->Ast()); + PushVariablesToNearestStatements(program_->Ast()); } ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent) @@ -64,6 +77,74 @@ ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent) return parent; } +void Transformer::AddVariableToNearestStatements(util::StringView name) +{ + /* + * Add variable declare like 'var ##var_1;' to nearest statements in namespace function or top level scope + * Record the variable name and scope in tempVarDeclStatements_ and will push the VariableDeclaration nodes + * to statements in PushVariablesToNearestStatements + */ + auto currentScope = Scope(); + while (currentScope != nullptr) { + if (currentScope->IsTSModuleScope()) { + auto node = currentScope->Node(); + ASSERT(node->IsTSModuleDeclaration()); + if (node->AsTSModuleDeclaration()->Body()->IsTSModuleBlock()) { + break; + } + } + if (currentScope->IsFunctionScope()) { + auto node = currentScope->Node(); + ASSERT(node->IsScriptFunction()); + if (!node->AsScriptFunction()->FunctionBodyIsExpression()) { + break; + } + } + currentScope = currentScope->Parent(); + } + tempVarDeclStatements_.insert({name, currentScope}); +} + +void Transformer::PushVariablesToNearestStatements(ir::BlockStatement *ast) +{ + /* + * Push the VariableDeclaration nodes to nearest statements + * For example, transform: + * namespace ns { + * ... + * } + * + * To: + * namespace ns { + * var ##var_1; + * ... + * } + */ + if (tempVarDeclStatements_.empty()) { + return; + } + for (auto it : tempVarDeclStatements_) { + auto *scope = it.second; + if (scope == nullptr) { + auto scopeCtx = binder::LexicalScope::Enter(Binder(), ast->Scope()); + ast->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, VariableParsingFlags::VAR, + nullptr, false)); + } else if (scope->IsFunctionScope()) { + auto *body = scope->Node()->AsScriptFunction()->Body(); + ASSERT(body->IsBlockStatement()); + auto scopeCtx = binder::LexicalScope::Enter(Binder(), scope); + body->AsBlockStatement()->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, + VariableParsingFlags::VAR, nullptr, false)); + } else if (scope->IsTSModuleScope()) { + auto *body = scope->Node()->AsTSModuleDeclaration()->Body(); + ASSERT(body->IsTSModuleBlock()); + auto scopeCtx = binder::LexicalScope::Enter(Binder(), scope); + body->AsTSModuleBlock()->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, + VariableParsingFlags::VAR, nullptr, false)); + } + } +} + binder::Scope *Transformer::FindExportVariableInTsModuleScope(util::StringView name) const { bool isExport = false; @@ -110,8 +191,7 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) auto scope = FindExportVariableInTsModuleScope(name); if (scope) { auto moduleName = FindTSModuleNameByScope(scope); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *res = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); SetOriginalNode(res, childNode); @@ -164,12 +244,607 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) SetOriginalNode(res, childNode); return res; } + case ir::AstNodeType::CLASS_DECLARATION: { + auto *node = childNode->AsClassDeclaration(); + DuringClass duringClass(&classList_, node->Definition()->GetName()); + node = VisitTSNodes(node)->AsClassDeclaration(); + auto res = VisitClassDeclaration(node); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::CLASS_EXPRESSION: { + auto *node = childNode->AsClassExpression(); + DuringClass duringClass(&classList_, node->Definition()->GetName()); + node = VisitTSNodes(node)->AsClassExpression(); + auto res = VisitClassExpression(node); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::CLASS_DEFINITION: { + auto *node = childNode->AsClassDefinition(); + VisitPrivateProperty(node); + VisitComputedProperty(node); + VisitTSParameterProperty(node); + auto res = VisitTSNodes(childNode); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: { + auto id = childNode->AsTSPrivateIdentifier()->Key()->AsIdentifier(); + auto name = FindPrivatePropertyBindName(id->Name()); + auto res = CreateReferenceIdentifier(name); + SetOriginalNode(res, childNode); + return res; + } default: { return VisitTSNodes(childNode); } } } +util::StringView Transformer::CreateNewVariable(bool needAddToStatements) +{ + util::StringView name = CreateNewVariableName(); + if (needAddToStatements) { + AddVariableToNearestStatements(name); + } + return name; +} + +util::StringView Transformer::CreateUniqueName(const std::string &head, size_t *index) const +{ + util::StringView name; + size_t idx = 0; + if (index != nullptr) { + idx = *index; + } + do { + idx++; + std::stringstream ss; + ss << head << std::to_string(idx); + auto s = ss.str(); + if (!Binder()->HasVariableName(util::StringView(s))) { + name = util::UString(s, Allocator()).View(); + break; + } + } while (true); + if (index != nullptr) { + *index = idx; + } + Binder()->AddDeclarationName(name); + return name; +} + +util::StringView Transformer::CreateNewVariableName() const +{ + auto name = CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD)); + return name; +} + +ir::UpdateNodes Transformer::VisitClassExpression(ir::ClassExpression *node) +{ + /* + * Transform: + * var c = class C { + * static a = 1 + * } + * + * To: + * var ##var_1; + * var c = (##var_1 = class C {}, + * ##var_1.a = 1, + * ##var_1) + */ + auto varName = CreateNewVariable(false); + auto staticProperty = VisitStaticProperty(node->Definition(), varName); + if (staticProperty.empty()) { + return node; + } + AddVariableToNearestStatements(varName); + + auto assignment = AllocNode(CreateReferenceIdentifier(varName), + node->AsExpression(), lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + ArenaVector sequence(Allocator()->Adapter()); + sequence.push_back(assignment); + for (auto *it : staticProperty) { + sequence.push_back(it->GetExpression()); + } + sequence.push_back(CreateReferenceIdentifier(varName)); + return AllocNode(std::move(sequence)); +} + +void Transformer::VisitComputedProperty(ir::ClassDefinition *node) +{ + /* + * Only create variable for the computed members with decorators or static class property + * The new value will be used in the decorators or static property initialize + * Transform: + * class C { + * @f + * [a](){} + * static [b] = 1 + * } + * + * To: + * var ##var_1; + * var ##var_2; + * class C { + * @f + * [##var_1 = a](){} + * static [##var_2 = b] = 1 + * } + */ + for (auto *it : node->Body()) { + if (it->IsClassProperty()) { + auto *classProperty = it->AsClassProperty(); + if (!classProperty->IsComputed() || (!classProperty->HasDecorators() && !classProperty->IsStatic())) { + continue; + } + auto *key = classProperty->Key(); + auto name = CreateNewVariable(); + auto *newKey = AllocNode(CreateReferenceIdentifier(name), + key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + classProperty->SetKey(newKey); + AddComputedPropertyBinding(it, name); + } else if (it->IsMethodDefinition()) { + auto *methodDefinition = it->AsMethodDefinition(); + if (!methodDefinition->Computed() || + (!methodDefinition->HasDecorators() && !methodDefinition->HasParamDecorators())) { + continue; + } + auto *key = methodDefinition->Key(); + auto name = CreateNewVariable(); + auto *newKey = AllocNode(CreateReferenceIdentifier(name), + key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + methodDefinition->SetKey(newKey); + AddComputedPropertyBinding(it, name); + } + } +} + +void Transformer::VisitPrivateProperty(ir::ClassDefinition *node) +{ + /* + * Create an unique variable name for private property member in class + * Transform: + * class C { + * #a = 1 + * } + * + * To: + * class C { + * ##${RecordName}#C#a#1 = 1 + * } + */ + for (auto *it : node->Body()) { + if (!it->IsClassProperty()) { + continue; + } + auto *key = it->AsClassProperty()->Key(); + if (!key->IsTSPrivateIdentifier()) { + continue; + } + auto name = key->AsTSPrivateIdentifier()->Key()->AsIdentifier()->Name(); + auto bindName = CreatePrivatePropertyBindName(name); + AddPrivatePropertyBinding(name, bindName); + } +} + +util::StringView Transformer::FindPrivatePropertyBindName(util::StringView name) +{ + for (size_t i = classList_.size() - 1; i >= 0; i--) { + auto res = classList_[i].bindNameMap->find(name); + if (res != classList_[i].bindNameMap->end()) { + return res->second; + } + } + UNREACHABLE(); +} + +util::StringView Transformer::CreatePrivatePropertyBindName(util::StringView name) +{ + std::stringstream head; + head << NEW_VAR_PREFIX << std::string(RecordName()); + for (auto it : classList_) { + head << PRIVATE_PROPERTY_SIGN << std::string(it.name); + } + head << PRIVATE_PROPERTY_SIGN << std::string(name) << PRIVATE_PROPERTY_SIGN; + size_t index = GetCurrentClassInfoPropertyIndex(); + auto uniqueName = CreateUniqueName(head.str(), &index); + SetCurrentClassInfoPropertyIndex(index); + return uniqueName; +} + +void Transformer::VisitTSParameterProperty(ir::ClassDefinition *node) +{ + /* + * Add class property for the parameter property declaration in constructor + * Transform: + * class C { + * constructor(public a = 1) {} + * } + * + * To: + * class C { + * constructor(public a = 1) { + * this.a = a; + * } + * } + */ + auto *func = node->Ctor()->Function(); + auto *body = func->Body(); + if (body == nullptr) { + return; + } + auto blockStatement = body->AsBlockStatement(); + for (auto *it : func->Params()) { + if (!it->IsTSParameterProperty()) { + continue; + } + auto *parameter = it->AsTSParameterProperty()->Parameter(); + util::StringView name; + // TSParameterPropert only can be identifier or assignment expression + if (parameter->IsIdentifier()) { + name = parameter->AsIdentifier()->Name(); + } else { + ASSERT(parameter->IsAssignmentExpression()); + auto *left = parameter->AsAssignmentExpression()->Left(); + ASSERT(left->IsIdentifier()); + name = left->AsIdentifier()->Name(); + } + auto left = AllocNode(AllocNode(), + AllocNode(name, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto right = CreateReferenceIdentifier(name); + auto assignment = AllocNode(left, right, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + blockStatement->AddStatementInFront(AllocNode(assignment)); + } +} + +std::vector Transformer::VisitStaticProperty(ir::ClassDefinition *node, + util::StringView name) +{ + /* + * Create statement for static class property + * If it's a conputed property, we should initialize it's new variable first. + * Transform: + * var ##var_1; + * class C { + * static a = 1 + * static [##var_1 = s] = 1 + * } + * + * To: + * var ##var_1; + * class C { + * } + * C.a = 1; + * ##var_1 = s; + * C[##var_1] = 1; + * + * TODO(xucheng): should support static private property + */ + std::vector res; + auto classDefinitionBody = node->Body(); + for (auto *it : classDefinitionBody) { + if (!it->IsClassProperty()) { + continue; + } + auto *classProperty = it->AsClassProperty(); + if (!classProperty->IsStatic()) { + continue; + } + if (classProperty->IsComputed()) { + res.push_back(AllocNode(classProperty->Key())); + } + auto right = classProperty->Value(); + if (right == nullptr) { + continue; + } + auto *member = GetClassMemberName(classProperty->Key(), classProperty->IsComputed(), classProperty); + auto left = AllocNode(CreateReferenceIdentifier(name), member, + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, classProperty->IsComputed(), false); + auto assignment = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + res.push_back(AllocNode(assignment)); + } + return res; +} + +ir::UpdateNodes Transformer::VisitClassDeclaration(ir::ClassDeclaration *node) +{ + // TODO(xucheng): maybe will support metadata later + auto name = node->Definition()->GetName(); + std::vector res; + bool hasClassDecorators = node->HasDecorators(); + if (hasClassDecorators) { + auto definiton = node->Definition(); + auto *clsExpression = AllocNode(definiton); + res.push_back(CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::LET, node, false, + clsExpression, false)); + } else { + res.push_back(node); + } + + auto staticProperty = VisitStaticProperty(node->Definition(), name); + if (!staticProperty.empty()) { + res.insert(res.end(), staticProperty.begin(), staticProperty.end()); + } + + auto classDefinitionBody = node->Definition()->Body(); + // decorators of static members, should be called after instance members + std::vector staticMemberDecorators; + for (auto *it : classDefinitionBody) { + if (it->IsMethodDefinition()) { + auto *definition = it->AsMethodDefinition(); + bool isStatic = definition->IsStatic(); + auto paramDecorators = CreateParamDecorators(name, definition, false, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + paramDecorators.begin(), paramDecorators.end()); + } else { + res.insert(res.end(), paramDecorators.begin(), paramDecorators.end()); + } + if (!definition->HasDecorators()) { + continue; + } + auto methodDecorators = CreateMethodDecorators(name, definition, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + methodDecorators.begin(), methodDecorators.end()); + } else { + res.insert(res.end(), methodDecorators.begin(), methodDecorators.end()); + } + } else if (it->IsClassProperty()) { + auto *classProperty = it->AsClassProperty(); + bool isStatic = classProperty->IsStatic(); + if (!classProperty->HasDecorators()) { + continue; + } + auto propertyDecorators = CreatePropertyDecorators(name, classProperty, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + propertyDecorators.begin(), propertyDecorators.end()); + } else { + res.insert(res.end(), propertyDecorators.begin(), propertyDecorators.end()); + } + } + } + + if (!staticMemberDecorators.empty()) { + res.insert(res.end(), staticMemberDecorators.begin(), staticMemberDecorators.end()); + } + + // constructor decorators + auto *ctor = node->Definition()->Ctor(); + auto ctorParamDecorators = CreateParamDecorators(name, ctor, true, false); + res.insert(res.end(), ctorParamDecorators.begin(), ctorParamDecorators.end()); + + // class decorators + if (hasClassDecorators) { + auto classDecorators = CreateClassDecorators(node); + res.insert(res.end(), classDecorators.begin(), classDecorators.end()); + } + if (res.size() == 1) { + return res.front(); + } + return res; +} + +std::vector Transformer::CreateParamDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isConstructor, + bool isStatic) +{ + /* + * Param decorators + * Transform: + * class C { + * f(@g a){} + * } + * + * To: + * class C { + * f(a){} + * } + * g(C.prototype, "f", 0) + * + * Static method or constructor will use constructor function of the class instead of prototype of class + */ + std::vector res; + auto paramsDecorators = node->GetParamDecorators(); + for (int i = paramsDecorators.size() - 1; i >= 0; i--) { + auto paramIndex = paramsDecorators[i].paramIndex; + auto decorators = paramsDecorators[i].decorators; + for (int j = decorators.size() - 1; j >= 0; j--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isConstructor || isStatic)); + arguments.push_back(isConstructor ? + CreateReferenceIdentifier(CONSTRUCTOR_NAME) : + GetClassMemberName(node->Key(), node->Computed(), node)); + arguments.push_back(AllocNode(paramIndex)); + auto *callExpr = AllocNode(decorators[j]->Expr(), + std::move(arguments), nullptr, false); + res.push_back(AllocNode(callExpr)); + } + } + return res; +} + +std::vector Transformer::CreatePropertyDecorators(util::StringView className, + ir::ClassProperty *node, + bool isStatic) +{ + /* + * Property decorators + * Transform: + * class C { + * @f a = 1 + * } + * + * To: + * class C { + * a = 1 + * } + * f(C.prototype, "a") + * + * Static property will use constructor function of the class instead of prototype of class + */ + std::vector res; + auto decorators = node->Decorators(); + for (int i = decorators.size() - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isStatic)); + arguments.push_back(GetClassMemberName(node->Key(), node->IsComputed(), node)); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + res.push_back(AllocNode(callExpr)); + } + return res; +} + +std::vector Transformer::CreateMethodDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isStatic) +{ + /* + * Method decorators and accessor decorators + * Transform: + * class C { + * @g + * f(){} + * } + * + * To: + * class C { + * f(){} + * } + * Object.defineProperty(C.prototype, "f", + * g(C.prototype, "f", Object.getOwnPropertyDescriptor(C.prototype, "f")) || + * Object.getOwnPropertyDescriptor(C.prototype, "f")); + * + * static method will use constructor function of the class instead of prototype of class + * If the decorator has a return value, it will be set as the new property of the method + */ + std::vector res; + auto decorators = node->Decorators(); + for (int i = decorators.size() - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isStatic)); + arguments.push_back(GetClassMemberName(node->Key(), node->Computed(), node)); + arguments.push_back(CreateGetOwnPropertyDescriptorCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node))); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + auto *getProperty = CreateGetOwnPropertyDescriptorCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node)); + auto newValue = AllocNode(callExpr, getProperty, + lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + + auto *defineProperty = CreateDefinePropertyCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node), newValue); + + res.push_back(AllocNode(defineProperty)); + } + return res; +} + +ir::Expression *Transformer::CreateDecoratorTarget(util::StringView className, bool targetCtor) +{ + if (targetCtor) { + return CreateReferenceIdentifier(className); + } + return CreateClassPrototype(className); +} + +ir::MemberExpression *Transformer::CreateClassPrototype(util::StringView className) +{ + auto *cls = CreateReferenceIdentifier(className); + return AllocNode(cls, AllocNode(CLASS_PROTOTYPE, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); +} + +ir::CallExpression *Transformer::CreateDefinePropertyCall(ir::Expression *target, + ir::Expression *key, + ir::Expression *value) +{ + auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); + auto *caller = AllocNode(id, AllocNode(FUNC_NAME_OF_DEFINE_PROPERTY, + Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(target); + arguments.push_back(key); + arguments.push_back(value); + return AllocNode(caller, std::move(arguments), nullptr, false); +} + +ir::CallExpression *Transformer::CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key) +{ + auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); + auto *caller = AllocNode(id, + AllocNode(FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(target); + arguments.push_back(key); + return AllocNode(caller, std::move(arguments), nullptr, false); +} + +ir::Expression *Transformer::GetClassMemberName(ir::Expression *key, bool isComputed, ir::Statement *node) +{ + if (isComputed) { + auto name = GetComputedPropertyBinding(node); + return AllocNode(name, Allocator()); + } + if (key->IsIdentifier()) { + return AllocNode(key->AsIdentifier()->Name()); + } else if (key->IsStringLiteral()) { + return AllocNode(key->AsStringLiteral()->Str()); + } else if (key->IsNumberLiteral()) { + return AllocNode(key->AsNumberLiteral()->Number(), key->AsNumberLiteral()->Str()); + } else if (key->IsBigIntLiteral()) { + return AllocNode(key->AsBigIntLiteral()->Str()); + } + UNREACHABLE(); + return nullptr; +} + +std::vector Transformer::CreateClassDecorators(ir::ClassDeclaration *node) +{ + /* + * Class decorators + * Transform: + * @f + * class C { + * } + * + * To: + * class C { + * } + * C = f(C) || C; + * + * If the decorator has a return value, it will be used as the new declaration of the class + */ + auto name = node->Definition()->GetName(); + auto decorators = node->Decorators(); + auto size = decorators.size(); + std::vector res; + for (int i = size - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateReferenceIdentifier(name)); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + auto left = CreateReferenceIdentifier(name); + auto id = CreateReferenceIdentifier(name); + auto right = AllocNode(callExpr, id, lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + auto *assignExpr = AllocNode(left, right, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + + res.push_back(AllocNode(assignExpr)); + } + return res; +} + ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node) { auto *express = node->ModuleReference(); @@ -179,8 +854,7 @@ ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDecla auto name = node->Id()->Name(); if (IsTsModule() && node->IsExport()) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *left = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); ir::Expression *right = CreateMemberExpressionFromQualified(express); @@ -303,8 +977,7 @@ ir::Expression *Transformer::CreateMemberExpressionFromQualified(ir::Expression ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); } ASSERT(node->IsIdentifier()); - auto *id = AllocNode(node->AsIdentifier()->Name(), Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(node->AsIdentifier()->Name()); return id; } @@ -329,12 +1002,10 @@ void Transformer::SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode ir::ExpressionStatement *Transformer::CreateTsModuleAssignment(util::StringView name) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *left = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); - auto *right = AllocNode(name, Allocator()); - right->AsIdentifier()->SetReference(); + auto *right = CreateReferenceIdentifier(name); auto *assignExpr = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); return AllocNode(assignExpr); } @@ -348,31 +1019,41 @@ ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util VariableParsingFlags flags, ir::AstNode *node, bool isExport, - ir::Expression *init) + ir::Expression *init, + bool needBinding) { - auto *ident = AllocNode(name, Allocator()); - ident->AsIdentifier()->SetReference(); + auto *ident = CreateReferenceIdentifier(name); auto *declarator = AllocNode(ident, init); ArenaVector declarators(Allocator()->Adapter()); declarators.push_back(declarator); - binder::Decl *decl = nullptr; - binder::DeclarationFlags declflag = isExport ? - binder::DeclarationFlags::EXPORT : - binder::DeclarationFlags::NONE; auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR; if (flags & VariableParsingFlags::VAR) { - decl = Binder()->AddDecl(node->Start(), declflag, name); } else if (flags & VariableParsingFlags::LET) { varKind = ir::VariableDeclaration::VariableDeclarationKind::LET; - decl = Binder()->AddDecl(node->Start(), declflag, name); } else { varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST; - decl = Binder()->AddDecl(node->Start(), declflag, name); } - auto *declaration = AllocNode(varKind, std::move(declarators), false); - decl->BindNode(declaration); + + lexer::SourcePosition startPos(0, 0); + if (node != nullptr) { + startPos = node->Start(); + } + if (needBinding) { + binder::Decl *decl = nullptr; + binder::DeclarationFlags declflag = isExport ? + binder::DeclarationFlags::EXPORT : + binder::DeclarationFlags::NONE; + if (flags & VariableParsingFlags::VAR) { + decl = Binder()->AddDecl(startPos, declflag, name); + } else if (flags & VariableParsingFlags::LET) { + decl = Binder()->AddDecl(startPos, declflag, name); + } else { + decl = Binder()->AddDecl(startPos, declflag, name); + } + decl->BindNode(declaration); + } return declaration; } @@ -383,19 +1064,8 @@ util::StringView Transformer::GetParamName(ir::TSModuleDeclaration *node, util:: if (!scope->HasVariableName(name)) { return name; } - - auto pramaName = name; - uint32_t idx = 0; - do { - std::stringstream ss; - ss << name; - idx++; - ss << "_" << std::to_string(idx); - util::UString internalName(ss.str(), Allocator()); - pramaName = internalName.View(); - } while (Binder()->HasVariableName(pramaName)); - Binder()->AddDeclarationName(pramaName); - return pramaName; + auto uniqueName = CreateUniqueName(std::string(name) + std::string(INDEX_DIVISION)); + return uniqueName; } ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node, @@ -411,8 +1081,7 @@ ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDec auto paramScopeCtx = binder::LexicalScope::Enter(Binder(), funcParamScope); ArenaVector params(Allocator()->Adapter()); - auto *parameter = AllocNode(paramName, Allocator()); - parameter->AsIdentifier()->SetReference(); + auto *parameter = CreateReferenceIdentifier(paramName); Binder()->AddParamDecl(parameter); params.push_back(parameter); @@ -458,8 +1127,7 @@ ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDec assignExpr, lexer::TokenType::PUNCTUATOR_LOGICAL_OR); if (isExport) { - auto *id = AllocNode(name, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(name); arguments.push_back(AllocNode(id, argument, lexer::TokenType::PUNCTUATOR_SUBSTITUTION)); } else { @@ -475,14 +1143,12 @@ ir::Expression *Transformer::CreateTsModuleParam(util::StringView paramName, boo { if (isExport) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); return AllocNode(id, AllocNode(paramName, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); } - auto *id = AllocNode(paramName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(paramName); return id; } @@ -524,4 +1190,11 @@ ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *n return res; } +ir::Identifier *Transformer::CreateReferenceIdentifier(util::StringView name) +{ + auto *node = AllocNode(name, Allocator()); + node->AsIdentifier()->SetReference(); + return node; +} + } // namespace panda::es2panda::parser diff --git a/es2panda/parser/transformer/transformer.h b/es2panda/parser/transformer/transformer.h index a69ec50c46..3ef64914db 100644 --- a/es2panda/parser/transformer/transformer.h +++ b/es2panda/parser/transformer/transformer.h @@ -32,11 +32,41 @@ struct TsModuleInfo { binder::Scope *scope; }; +using PrivatePropertyMap = std::unordered_map; +using ComputedPropertyMap = std::unordered_map; + +struct ClassInfo { + util::StringView name; + size_t propertyIndex; + PrivatePropertyMap *bindNameMap; + ComputedPropertyMap *computedPropertyMap; +}; + +class DuringClass { +public: + explicit DuringClass(ArenaVector *classList, util::StringView name) + { + classList_ = classList; + classList_->push_back({name, 0, &bindNameMap_, &computedPropertyMap_}); + } + + ~DuringClass() + { + classList_->pop_back(); + } + +private: + PrivatePropertyMap bindNameMap_ {}; + ComputedPropertyMap computedPropertyMap_ {}; + ArenaVector *classList_ {nullptr}; +}; + class Transformer { public: explicit Transformer(panda::ArenaAllocator *allocator) : program_(nullptr), - tsModuleList_(allocator->Adapter()) + tsModuleList_(allocator->Adapter()), + classList_(allocator->Adapter()) { } NO_COPY_SEMANTIC(Transformer); @@ -45,27 +75,72 @@ public: void Transform(Program *program); private: + static constexpr std::string_view PRIVATE_PROPERTY_SIGN = "#"; + static constexpr std::string_view NEW_VAR_PREFIX = "##"; + static constexpr std::string_view NEW_VAR_HEAD = "var_"; + static constexpr std::string_view INDEX_DIVISION = "_"; + static constexpr std::string_view CONSTRUCTOR_NAME = "undefined"; + static constexpr std::string_view CLASS_PROTOTYPE = "prototype"; + static constexpr std::string_view OBJECT_VAR_NAME = "Object"; + static constexpr std::string_view FUNC_NAME_OF_DEFINE_PROPERTY = "defineProperty"; + static constexpr std::string_view FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR = "getOwnPropertyDescriptor"; + void TransformFromTS(); + + void AddVariableToNearestStatements(util::StringView name); + void PushVariablesToNearestStatements(ir::BlockStatement *ast); + ir::AstNode *VisitTSNodes(ir::AstNode *parent); ir::UpdateNodes VisitTSNode(ir::AstNode *childNode); ir::UpdateNodes VisitTsModuleDeclaration(ir::TSModuleDeclaration *childNode, bool isExport = false); std::vector VisitExportNamedVariable(ir::Statement *decl); ir::AstNode *VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node); + ir::UpdateNodes VisitClassDeclaration(ir::ClassDeclaration *node); + ir::UpdateNodes VisitClassExpression(ir::ClassExpression *node); + void VisitTSParameterProperty(ir::ClassDefinition *node); + std::vector VisitStaticProperty(ir::ClassDefinition *node, util::StringView name); + void VisitPrivateProperty(ir::ClassDefinition *node); + void VisitComputedProperty(ir::ClassDefinition *node); + ir::VariableDeclaration *CreateVariableDeclarationWithIdentify(util::StringView name, VariableParsingFlags flags, ir::AstNode *node, bool isExport, - ir::Expression *init = nullptr); + ir::Expression *init = nullptr, + bool needBinding = true); ir::CallExpression *CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node, util::StringView paramName, bool isExport = false); ir::Expression *CreateTsModuleParam(util::StringView paramName, bool isExport); ir::ExpressionStatement *CreateTsModuleAssignment(util::StringView name); ir::Expression *CreateMemberExpressionFromQualified(ir::Expression *node); + std::vector CreateClassDecorators(ir::ClassDeclaration *node); + std::vector CreateMethodDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isStatic); + std::vector CreatePropertyDecorators(util::StringView className, + ir::ClassProperty *node, + bool isStatic); + ir::CallExpression *CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key); + ir::CallExpression *CreateDefinePropertyCall(ir::Expression *target, ir::Expression *key, ir::Expression *value); + std::vector CreateParamDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isConstructor, + bool isStatic); + ir::MemberExpression *CreateClassPrototype(util::StringView className); + ir::Expression *CreateDecoratorTarget(util::StringView className, bool isStatic); + ir::Identifier *CreateReferenceIdentifier(util::StringView name); + util::StringView CreatePrivatePropertyBindName(util::StringView name); + util::StringView CreateNewVariable(bool needAddToStatements = true); + util::StringView CreateNewVariableName() const; + util::StringView CreateUniqueName(const std::string &head, size_t *index = nullptr) const; + util::StringView GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const; util::StringView GetParamName(ir::TSModuleDeclaration *node, util::StringView name) const; + ir::Expression *GetClassMemberName(ir::Expression *key, bool isComputed, ir::Statement *node); binder::Scope *FindExportVariableInTsModuleScope(util::StringView name) const; binder::Variable *FindTSModuleVariable(const ir::Expression *node, binder::Scope *scope) const; + util::StringView FindPrivatePropertyBindName(util::StringView name); void AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier); bool IsInstantiatedTSModule(const ir::Expression *node) const; void SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const; @@ -125,8 +200,43 @@ private: return program_->ModuleRecord(); } + util::StringView RecordName() const + { + return program_->RecordName(); + } + + size_t GetCurrentClassInfoPropertyIndex() const + { + return classList_.back().propertyIndex; + } + + void SetCurrentClassInfoPropertyIndex(size_t newIndex) + { + classList_.back().propertyIndex = newIndex; + } + + void AddPrivatePropertyBinding(util::StringView name, util::StringView bindName) + { + classList_.back().bindNameMap->insert({name, bindName}); + } + + void AddComputedPropertyBinding(ir::Statement *property, util::StringView name) + { + classList_.back().computedPropertyMap->insert({property, name}); + } + + util::StringView GetComputedPropertyBinding(ir::Statement *property) + { + auto classInfo = classList_.back(); + auto res = classInfo.computedPropertyMap->find(property); + ASSERT(res != classInfo.computedPropertyMap->end()); + return res->second; + } + Program *program_; ArenaVector tsModuleList_; + ArenaVector classList_; + std::unordered_map tempVarDeclStatements_ {}; }; } // namespace panda::es2panda::parser diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt new file mode 100644 index 0000000000..2b2f2e1b92 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt @@ -0,0 +1,2 @@ +1 +3 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts new file mode 100644 index 0000000000..5df2ae0b4f --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + constructor(public a : number = 1, public b : number = 2) + { + this.b = 3; + } +} + +var c : C = new C(); +print(c.a); +print(c.b); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt new file mode 100644 index 0000000000..1191247b6d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts new file mode 100644 index 0000000000..ee6cd3ebd8 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + a = 2; + static a = 1; +} + +print(C.a); + +var c = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt new file mode 100644 index 0000000000..1191247b6d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts new file mode 100644 index 0000000000..bcc5b639aa --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +class A { + #a = 1; + a = 2; + PrintA() { + print(this.#a); + print(this.a); + } +} + +var a : A = new A(); +a.PrintA(); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts new file mode 100644 index 0000000000..75e33a4d35 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +let a = class { + static a = 1; +} + +print(a.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt new file mode 100644 index 0000000000..e329b95a8d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt @@ -0,0 +1 @@ +[1+2] diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts new file mode 100644 index 0000000000..d8b20bbdf5 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + [1 + 2] () {print("[1+2]")}; +} + +var c : C = new C(); +c[1 + 2](); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts new file mode 100644 index 0000000000..57c8cdf68a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(a = class {static a = 1;}) { + print(a.a); +} +f(); + diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts new file mode 100644 index 0000000000..a30e988212 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C{ + static [1] = 1; +} +print(C[1]) diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts new file mode 100644 index 0000000000..d5bd06afc5 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + constructor(public a ?: number) + { + this.a = 1; + } +} + +var c : C = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt new file mode 100644 index 0000000000..bcba9b8c46 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts new file mode 100644 index 0000000000..206ad323f4 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(constructor) { + print("test-ts-decorators-1"); +} + +@f +class C {} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt new file mode 100644 index 0000000000..1af4bf8965 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt @@ -0,0 +1,4 @@ +1 +1 +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts new file mode 100644 index 0000000000..9f6eea9623 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a:string = "1" +var b:string = "2" + +function f1(target, key, property){ + print(key) + print(a) +} +function f2(target, key, property){ + print(key) + print(a) + a=b +} +class C{ + @f1 + @f2 + [a](){}; + [b](){}; +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt new file mode 100644 index 0000000000..417130426e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt @@ -0,0 +1,2 @@ +3 +[1+2] diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts new file mode 100644 index 0000000000..a64af05e0b --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, key, property) { + print(key); +} + +class C { + @f + [1 + 2] () {print("[1+2]")}; +} + +var c : C = new C(); +c[1 + 2](); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt new file mode 100644 index 0000000000..afacc5d03d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt @@ -0,0 +1,2 @@ +g1 +g2 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts new file mode 100644 index 0000000000..6cd5992735 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(constructor) { + return class extends constructor{ + g1() { + print("g1"); + } + } +} + +@f +class C{ + g2() { + print("g2"); + } +} + +var c = new C() +c.g1() +c.g2() diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt new file mode 100644 index 0000000000..2cdda450af --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt @@ -0,0 +1,4 @@ +true +false +true +false diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts new file mode 100644 index 0000000000..3e5929ee35 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, key, property) { + property.enumerable=true + return property; +} + +class C{ + @f + a1 (){} + a2 (){return 1} + @f + static b1 (){} + static b2 (){} +} + +print(Object.getOwnPropertyDescriptor(C.prototype,"a1")!.enumerable) +print(Object.getOwnPropertyDescriptor(C.prototype,"a2")!.enumerable) +print(Object.getOwnPropertyDescriptor(C,"b1")!.enumerable) +print(Object.getOwnPropertyDescriptor(C,"b2")!.enumerable) diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt new file mode 100644 index 0000000000..eb1d506a3c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-2 flag-1 +test-ts-decorators-2 flag-2 +test-ts-decorators-2 flag-1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts new file mode 100644 index 0000000000..d98f0179c7 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f1(constructor) { + print("test-ts-decorators-2 flag-1"); +} + +function f2() { + return function(constructor) { + print("test-ts-decorators-2 flag-2");} +} + +@f1 +@f2() +@f1 +class C {} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt new file mode 100644 index 0000000000..6903fe99ab --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt @@ -0,0 +1,10 @@ +test-ts-decorators-3 +a +test-ts-decorators-3 +1 +test-ts-decorators-3 +b +test-ts-decorators-3 +c +test-ts-decorators-3 +3 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts new file mode 100644 index 0000000000..b112358573 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, propertyKey, descriptor) { + print("test-ts-decorators-3"); + print(propertyKey); +} + +class C { + @f + a() {} + + @f + 1() {} + + @f + "b"() {} + + @f + static [1+2]() {} + + @f + ["c"]() {} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt new file mode 100644 index 0000000000..e001f89fac --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-4 +a +123 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts new file mode 100644 index 0000000000..54f8eae39c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, propertyKey) { + print("test-ts-decorators-4"); + print(propertyKey); +} + +class C { + @f + a : string = "123"; +} + +var c = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt new file mode 100644 index 0000000000..8d8916c04d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt @@ -0,0 +1,21 @@ +test-ts-decorators-5 +g2 +2 +test-ts-decorators-5 +g2 +0 +test-ts-decorators-5 +g2 +0 +test-ts-decorators-5 +g1 +2 +test-ts-decorators-5 +g1 +0 +test-ts-decorators-5 +g1 +0 +test-ts-decorators-5 +undefined +0 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts new file mode 100644 index 0000000000..20879b8224 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, propertyKey, b) { + print("test-ts-decorators-5"); + print(propertyKey); + print(b); +} + +class C { + static g1(@f @f a, b, @f {c}){} + + g2(@f @f a, b, @f {c}){} + + constructor(@f a1,b,c){} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt new file mode 100644 index 0000000000..81e4a7a02e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-6 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts new file mode 100644 index 0000000000..a71e3f4aa0 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(ctor) { + return class extends ctor{ + constructor(){ + super(); + this.s = "test-ts-decorators-6"; + } + } +} + +@f +class C{} + +var c = new C(); +print(c.s); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt new file mode 100644 index 0000000000..5a9364b7b4 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt @@ -0,0 +1,18 @@ +methodDecorator2 +methodDecorator1 +propertyDecorator2 +propertyDecorator1 +paramDecorator2 +paramDecorator1 +methodDecorator2 +methodDecorator1 +propertyDecorator2 +propertyDecorator1 +paramDecorator2 +paramDecorator1 +methodDecorator2 +methodDecorator1 +paramDecorator2 +paramDecorator1 +classDecorator2 +classDecorator1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts new file mode 100644 index 0000000000..7359721058 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 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. + */ + + +function classDecorator1(ctor) +{ + print("classDecorator1") +} + +function classDecorator2() +{ + return (ctor)=>{print("classDecorator2")} +} + +function methodDecorator1(target, key, property) +{ + print("methodDecorator1") +} + +function methodDecorator2() +{ + return (target, key, property)=>{print("methodDecorator2")} +} + +function propertyDecorator1(target, key) +{ + print("propertyDecorator1") +} + +function propertyDecorator2() +{ + return (target, key)=>{print("propertyDecorator2")} +} + +function paramDecorator1(target, key, index) +{ + print("paramDecorator1"); +} + +function paramDecorator2() +{ + return (target, key, index)=>{print("paramDecorator2")} +} + +@classDecorator1 +@classDecorator2() +class C { + @methodDecorator1 + @methodDecorator2() + get x() {return 1;} + + @propertyDecorator1 + @propertyDecorator2() + static b : number = 1; + + @propertyDecorator1 + @propertyDecorator2() + a : number = 1; + + @methodDecorator1 + @methodDecorator2() + static g1(a, @paramDecorator1 @paramDecorator2() b){} + + @methodDecorator1 + @methodDecorator2() + g2(a, @paramDecorator1 @paramDecorator2() b){} + + constructor(a, b, @paramDecorator1 @paramDecorator2() c){} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt new file mode 100644 index 0000000000..34756f555f --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-8 +1 +123 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts new file mode 100644 index 0000000000..8ca133894d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f(target, propertyKey) { + print("test-ts-decorators-8"); + print(propertyKey); +} + +class C { + @f + static [1] : string = "123"; + /* + * TODO(xucheng): test computer property when class support it + * @f + * [2] : string = "123"; + */ +} + +print(C[1]); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt new file mode 100644 index 0000000000..0886de01d5 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-9 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts new file mode 100644 index 0000000000..37d54afc1c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 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. + */ + + +const s : unique symbol = Symbol() +function f(target, propertyKey) { + print("test-ts-decorators-9"); +} +class C{ + @f + static [s] : any; +} diff --git a/es2panda/test/parser/ts/test_decorator-expected.txt b/es2panda/test/parser/ts/test_decorator-expected.txt index 0477a6de92..51261278f4 100644 --- a/es2panda/test/parser/ts/test_decorator-expected.txt +++ b/es2panda/test/parser/ts/test_decorator-expected.txt @@ -67,40 +67,11 @@ } } }, - "decorators": [ - { - "type": "Decorator", - "expression": { - "type": "Identifier", - "name": "g", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 18 - }, - "end": { - "line": 27, - "column": 19 - } - } - }, - "loc": { - "start": { - "line": 27, - "column": 17 - }, - "end": { - "line": 27, - "column": 19 - } - } - } - ], + "decorators": [], "loc": { "start": { "line": 27, - "column": 17 + "column": 20 }, "end": { "line": 27, diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 8b79f1de9f..bdfa45dbb5 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -394,7 +394,7 @@ class Runner: self.failed = 0 self.passed = 0 self.es2panda = path.join(args.build_dir, 'es2abc') - self.test_abc = path.join(args.build_dir, 'runner_test.abc') + self.build_dir = args.build_dir self.cmd_prefix = [] self.ark_js_vm = "" self.ld_library_path = "" @@ -788,9 +788,11 @@ class CompilerTest(Test): Test.__init__(self, test_path, flags) def run(self, runner): + test_abc_name = ("%s.abc" % (path.splitext(self.path)[0])).replace("/", "_") + test_abc_path = path.join(runner.build_dir, test_abc_name) es2abc_cmd = runner.cmd_prefix + [runner.es2panda] es2abc_cmd.extend(self.flags) - es2abc_cmd.extend(["--output=" + runner.test_abc]) + es2abc_cmd.extend(["--output=" + test_abc_path]) es2abc_cmd.append(self.path) self.log_cmd(es2abc_cmd) @@ -804,7 +806,7 @@ class CompilerTest(Test): ld_library_path = runner.ld_library_path os.environ.setdefault("LD_LIBRARY_PATH", ld_library_path) run_abc_cmd = [runner.ark_js_vm] - run_abc_cmd.extend([runner.test_abc]) + run_abc_cmd.extend([test_abc_path]) self.log_cmd(run_abc_cmd) process = subprocess.Popen(run_abc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -821,7 +823,7 @@ class CompilerTest(Test): if not self.passed: self.error = err.decode("utf-8", errors="ignore") - os.remove(runner.test_abc) + os.remove(test_abc_path) return self diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..b7cfa8daf8 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -45,7 +45,6 @@ es2panda/test/TypeScript/tests/cases/compiler/parseEntityNameWithReservedWord.ts es2panda/test/TypeScript/tests/cases/compiler/shebang.ts es2panda/test/TypeScript/tests/cases/compiler/sigantureIsSubTypeIfTheyAreIdentical.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMap-LineBreaks.ts -es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDecorators.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPattern2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPattern2.ts -- Gitee From a3246523a3e79e6f456f0c04fc196ae717f9b427 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Wed, 12 Oct 2022 11:46:21 +0800 Subject: [PATCH 19/59] Fix arrow functiontype and type assertion parse 1. An arrow function variable may have arrow function type, we should support this case. 2. We parser < as arrow function first, but we may throw error when we parser. So we should add try catch here. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5VAG1 Test: parser tests, compier tests, test262 Signed-off-by: xucheng46 Change-Id: I1693ef99eb14c9362caa41b25f8d059a4acac7ff --- es2panda/parser/expressionParser.cpp | 7 +- es2panda/parser/parserImpl.cpp | 71 +++- es2panda/parser/parserImpl.h | 1 + .../ts/test-arrow-function1-expected.txt | 175 ++++++++ .../test/parser/ts/test-arrow-function1.ts | 17 + .../ts/test-arrow-function2-expected.txt | 378 ++++++++++++++++++ .../test/parser/ts/test-arrow-function2.ts | 21 + es2panda/test/test_tsc_ignore_list.txt | 7 - 8 files changed, 650 insertions(+), 27 deletions(-) create mode 100644 es2panda/test/parser/ts/test-arrow-function1-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function1.ts create mode 100644 es2panda/test/parser/ts/test-arrow-function2-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function2.ts diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022..bcd2a0f2c9 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -165,7 +165,12 @@ ir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags) const auto startPos = lexer_->Save(); // TODO(rsipka): ParseTsGenericArrowFunction and ParseTsTypeAssertion might be in a common function - ir::Expression *expr = ParseTsGenericArrowFunction(); + ir::Expression *expr = nullptr; + try { + expr = ParseTsGenericArrowFunction(); + } catch ([[maybe_unused]] const class Error &e) { + expr = nullptr; + } if (expr != nullptr) { return expr; } diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 09a79b3c26..b9e18288d4 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -1606,6 +1606,54 @@ ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type return intersectionType; } +bool ParserImpl::IsTsFunctionType() +{ + ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); + const auto startPos = lexer_->Save(); + lexer_->NextToken(); // eat '(' + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + lexer_->Rewind(startPos); + return true; + } + + try { + ParseModifiers(); + if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || + (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) { + lexer_->NextToken(); + } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { + ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); + } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN); + } else { + lexer_->Rewind(startPos); + return false; + } + } catch ([[maybe_unused]] const class Error &e) { + lexer_->Rewind(startPos); + return false; + } + + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) { + lexer_->Rewind(startPos); + return true; + } + + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + lexer_->NextToken(); // eat ')' + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { + lexer_->Rewind(startPos); + return true; + } + } + lexer_->Rewind(startPos); + return false; +} + ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError) { if (typeAnnotation) { @@ -1635,25 +1683,16 @@ ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *t return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor); } - const auto startPos = lexer_->Save(); + if (IsTsFunctionType()) { + return ParseTsFunctionType(typeStart, false, throwError); + } + ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer_->NextToken(); // eat '(' TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS; ir::Expression *type = ParseTsTypeAnnotation(&options); - if (!type) { - lexer_->Rewind(startPos); - return ParseTsFunctionType(typeStart, false, throwError); - } - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - lexer_->Rewind(startPos); - return ParseTsFunctionType(typeStart, false, throwError); - } - if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { ThrowSyntaxError("')' expected"); } @@ -1661,12 +1700,6 @@ ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *t lexer::SourcePosition endLoc = lexer_->GetToken().End(); lexer_->NextToken(); // eat ')' - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { - lexer_->Rewind(startPos); - - return ParseTsFunctionType(typeStart, false, throwError); - } - auto *result = AllocNode(type); result->SetRange({typeStart, endLoc}); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 16d2929ce9..d1e663a1e3 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -243,6 +243,7 @@ private: ir::TSUnionType *ParseTsUnionType(ir::Expression *type, bool restrictExtends); ir::Expression *ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError); ir::TSArrayType *ParseTsArrayType(ir::Expression *elementType); + bool IsTsFunctionType(); ir::Expression *ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType, bool throwError, bool abstractConstructor = false); ir::TSTypeParameter *ParseTsMappedTypeParameter(); diff --git a/es2panda/test/parser/ts/test-arrow-function1-expected.txt b/es2panda/test/parser/ts/test-arrow-function1-expected.txt new file mode 100644 index 0000000000..b853bf6b3d --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function1-expected.txt @@ -0,0 +1,175 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "returnType": { + "type": "TSParenthesizedType", + "typeAnnotation": { + "type": "TSFunctionType", + "params": [], + "returnType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "body": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "body": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 17, + "column": 39 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 40 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-arrow-function1.ts b/es2panda/test/parser/ts/test-arrow-function1.ts new file mode 100644 index 0000000000..36780a4d9a --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function1.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +const f = (): (() => number) => () => 1; diff --git a/es2panda/test/parser/ts/test-arrow-function2-expected.txt b/es2panda/test/parser/ts/test-arrow-function2-expected.txt new file mode 100644 index 0000000000..d1b0f26a3f --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function2-expected.txt @@ -0,0 +1,378 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 19 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "body": { + "type": "TSTypeAssertion", + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "expression": { + "type": "ObjectExpression", + "properties": [ + { + "type": "Property", + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 20, + "column": 24 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 27 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 20, + "column": 27 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 20 + }, + "end": { + "line": 20, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 33 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-arrow-function2.ts b/es2panda/test/parser/ts/test-arrow-function2.ts new file mode 100644 index 0000000000..d74b837286 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function2.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + a : number = 0; +} +var b = () => ((({ a: 1 }))); + diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..850a0347d4 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -1,9 +1,6 @@ es2panda/test/TypeScript/tests/cases/compiler/ambientClassOverloadForFunction.ts -es2panda/test/TypeScript/tests/cases/compiler/arrowFunctionWithObjectLiteralBody5.ts -es2panda/test/TypeScript/tests/cases/compiler/arrowFunctionWithObjectLiteralBody6.ts es2panda/test/TypeScript/tests/cases/compiler/assertionFunctionsCanNarrowByDiscriminant.ts es2panda/test/TypeScript/tests/cases/compiler/bom-utf16be.ts -es2panda/test/TypeScript/tests/cases/compiler/castTest.ts es2panda/test/TypeScript/tests/cases/compiler/classFunctionMerging.ts es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInType.ts es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInterfaceMembers.ts @@ -24,7 +21,6 @@ es2panda/test/TypeScript/tests/cases/compiler/exportRedeclarationTypeAliases.ts es2panda/test/TypeScript/tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts es2panda/test/TypeScript/tests/cases/compiler/fileWithNextLine2.ts es2panda/test/TypeScript/tests/cases/compiler/genericRecursiveImplicitConstructorErrors2.ts -es2panda/test/TypeScript/tests/cases/compiler/getterSetterNonAccessor.ts es2panda/test/TypeScript/tests/cases/compiler/globalIsContextualKeyword.ts es2panda/test/TypeScript/tests/cases/compiler/implementsInClassExpression.ts es2panda/test/TypeScript/tests/cases/compiler/inferenceErasedSignatures.ts @@ -36,11 +32,8 @@ es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForIn_ES6.ts es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForOf_ES5.ts es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForOf_ES6.ts es2panda/test/TypeScript/tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts -es2panda/test/TypeScript/tests/cases/compiler/objectLitGetterSetter.ts -es2panda/test/TypeScript/tests/cases/compiler/overloadResolutionOverNonCTObjectLit.ts es2panda/test/TypeScript/tests/cases/compiler/overloadedConstructorFixesInferencesAppropriately.ts es2panda/test/TypeScript/tests/cases/compiler/parameterInitializerBeforeDestructuringEmit.ts -es2panda/test/TypeScript/tests/cases/compiler/parseArrowFunctionWithFunctionReturnType.ts es2panda/test/TypeScript/tests/cases/compiler/parseEntityNameWithReservedWord.ts es2panda/test/TypeScript/tests/cases/compiler/shebang.ts es2panda/test/TypeScript/tests/cases/compiler/sigantureIsSubTypeIfTheyAreIdentical.ts -- Gitee From 5afba17e665be900c389b41fa09e648f2a2b50f0 Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Thu, 27 Oct 2022 15:21:49 +0800 Subject: [PATCH 20/59] Fix watching 'this' variable failure && showing local variables in IDE for es2panda Issue: I5Y1G7 Signed-off-by: gavin1012_hw Change-Id: Ibcbad9cf911b4bbc902f0d15a96d7858dc093851 --- es2panda/binder/binder.h | 12 ++++++------ es2panda/ir/expressions/thisExpression.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 414ff63344..5d3edaaf95 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -128,9 +128,9 @@ public: bool HasVariableName(const util::StringView &name) const; static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments"; - static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f"; - static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt"; - static constexpr std::string_view MANDATORY_PARAM_THIS = "=t"; + static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj"; + static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget"; + static constexpr std::string_view MANDATORY_PARAM_THIS = "this"; static constexpr std::string_view CJS_MANDATORY_PARAM_EXPORTS = "exports"; static constexpr std::string_view CJS_MANDATORY_PARAM_REQUIRE = "require"; @@ -142,9 +142,9 @@ public: static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3; static constexpr uint32_t CJS_MANDATORY_PARAMS_NUMBER = 8; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f"; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt"; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "0funcObj"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "0newTarget"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "0this"; static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0"; static constexpr std::string_view ANONYMOUS_FUNC_NAME = ""; diff --git a/es2panda/ir/expressions/thisExpression.cpp b/es2panda/ir/expressions/thisExpression.cpp index 2bd432c787..dde3633ac7 100644 --- a/es2panda/ir/expressions/thisExpression.cpp +++ b/es2panda/ir/expressions/thisExpression.cpp @@ -36,7 +36,7 @@ void ThisExpression::Compile(compiler::PandaGen *pg) const ASSERT(res.variable && res.variable->IsLocalVariable()); if (pg->isDebuggerEvaluateExpressionMode()) { - pg->LoadObjByNameViaDebugger(this, "this", true); + pg->LoadObjByNameViaDebugger(this, binder::Binder::MANDATORY_PARAM_THIS, true); } else { pg->LoadAccFromLexEnv(this, res); } -- Gitee From e503813a4e2dcbe24813b36cd7e3c4f5233fe933 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Thu, 27 Oct 2022 03:44:26 +0000 Subject: [PATCH 21/59] Add strict mode reserved words of js Issue: https://e.gitee.com/open_harmony/dashboard?issue=I5Y0MO Test: test262,parser tests, compiler tests Signed-off-by: zhangrengao Change-Id: Ib0f870b27d89ad86c8225e133968366c58760145 --- es2panda/lexer/token/token.cpp | 21 +++ es2panda/lexer/token/token.h | 1 + es2panda/parser/expressionParser.cpp | 4 +- es2panda/parser/parserImpl.cpp | 13 ++ es2panda/parser/parserImpl.h | 1 + es2panda/parser/statementParser.cpp | 4 +- ...unction-declaration-arguments-expected.txt | 1 + .../js/function-declaration-arguments.js | 4 + .../js/function-declaration-is-expected.txt | 101 ++++++++++++ .../test/parser/js/function-declaration-is.js | 4 + ...function-expression-arguments-expected.txt | 1 + .../js/function-expression-arguments.js | 4 + .../js/function-expression-is-expected.txt | 145 ++++++++++++++++++ .../test/parser/js/function-expression-is.js | 4 + 14 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 es2panda/test/parser/js/function-declaration-arguments-expected.txt create mode 100644 es2panda/test/parser/js/function-declaration-arguments.js create mode 100644 es2panda/test/parser/js/function-declaration-is-expected.txt create mode 100644 es2panda/test/parser/js/function-declaration-is.js create mode 100644 es2panda/test/parser/js/function-expression-arguments-expected.txt create mode 100644 es2panda/test/parser/js/function-expression-arguments.js create mode 100644 es2panda/test/parser/js/function-expression-is-expected.txt create mode 100644 es2panda/test/parser/js/function-expression-is.js diff --git a/es2panda/lexer/token/token.cpp b/es2panda/lexer/token/token.cpp index 12521b9dad..ba04e5d974 100644 --- a/es2panda/lexer/token/token.cpp +++ b/es2panda/lexer/token/token.cpp @@ -92,6 +92,27 @@ bool Token::IsReservedTypeName() const } } +bool Token::IsJsStrictReservedWord() const +{ + switch (keywordType_) + { + case TokenType::KEYW_ARGUMENTS: + case TokenType::KEYW_EVAL: + case TokenType::KEYW_STATIC: + case TokenType::KEYW_PRIVATE: + case TokenType::KEYW_PROTECTED: + case TokenType::KEYW_PUBLIC: + case TokenType::KEYW_IMPLEMENTS: + case TokenType::KEYW_INTERFACE: + case TokenType::KEYW_PACKAGE: + case TokenType::KEYW_LET: + case TokenType::KEYW_YIELD: + return true; + default: + return false; + } +} + bool Token::IsBinaryToken(TokenType type) { return (type >= TokenType::PUNCTUATOR_NULLISH_COALESCING && type <= TokenType::PUNCTUATOR_EXPONENTIATION); diff --git a/es2panda/lexer/token/token.h b/es2panda/lexer/token/token.h index 46a87d432c..26edb60d38 100644 --- a/es2panda/lexer/token/token.h +++ b/es2panda/lexer/token/token.h @@ -116,6 +116,7 @@ public: bool IsPropNameLiteral() const; bool IsKeyword() const; bool IsReservedTypeName() const; + bool IsJsStrictReservedWord() const; static bool IsBinaryToken(TokenType type); static bool IsBinaryLvalueToken(TokenType type); diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022..ed568b4c80 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -2344,9 +2344,7 @@ ir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStat ThrowSyntaxError("Expected an identifier."); } - if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) { - ThrowSyntaxError("Unexpected reserved word in strict mode."); - } + CheckStrictReservedWord(); ident = AllocNode(lexer_->GetToken().Ident(), Allocator()); ident->SetRange(lexer_->GetToken().Loc()); diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 4fa6a28421..a9e6e4b745 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -3546,4 +3546,17 @@ bool ParserImpl::IsDtsFile() const return program_.IsDtsFile(); } +void ParserImpl::CheckStrictReservedWord() const +{ + if (Extension() == ScriptExtension::JS) { + if (lexer_->GetToken().IsJsStrictReservedWord()) { + ThrowSyntaxError("Unexpected reserved word in strict mode."); + } + } else { + if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) { + ThrowSyntaxError("Unexpected reserved word in strict mode."); + } + } +} + } // namespace panda::es2panda::parser diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 16d2929ce9..ec1c0e6aa5 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -408,6 +408,7 @@ private: ir::ExportNamedDeclaration *ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc, ArenaVector &&decorators); ir::Identifier *ParseNamedExport(const lexer::Token &exportedToken); + void CheckStrictReservedWord() const; // StatementParser.Cpp diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 6710605b58..51ba7e85f6 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -1091,8 +1091,8 @@ ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymou ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword"); } - if (!isDeclare && lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) { - ThrowSyntaxError("Unexpected reserved word in strict mode."); + if (!isDeclare) { + CheckStrictReservedWord(); } util::StringView ident = lexer_->GetToken().Ident(); diff --git a/es2panda/test/parser/js/function-declaration-arguments-expected.txt b/es2panda/test/parser/js/function-declaration-arguments-expected.txt new file mode 100644 index 0000000000..5ee5461ec9 --- /dev/null +++ b/es2panda/test/parser/js/function-declaration-arguments-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected reserved word in strict mode. [function-declaration-arguments.js:3:10] diff --git a/es2panda/test/parser/js/function-declaration-arguments.js b/es2panda/test/parser/js/function-declaration-arguments.js new file mode 100644 index 0000000000..696c3c46cf --- /dev/null +++ b/es2panda/test/parser/js/function-declaration-arguments.js @@ -0,0 +1,4 @@ +'use strict' + +function arguments() { +} \ No newline at end of file diff --git a/es2panda/test/parser/js/function-declaration-is-expected.txt b/es2panda/test/parser/js/function-declaration-is-expected.txt new file mode 100644 index 0000000000..140342c6b1 --- /dev/null +++ b/es2panda/test/parser/js/function-declaration-is-expected.txt @@ -0,0 +1,101 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "StringLiteral", + "value": "use strict", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + { + "type": "FunctionDeclaration", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "is", + "decorators": [], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 12 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/js/function-declaration-is.js b/es2panda/test/parser/js/function-declaration-is.js new file mode 100644 index 0000000000..6db6828316 --- /dev/null +++ b/es2panda/test/parser/js/function-declaration-is.js @@ -0,0 +1,4 @@ +'use strict' + +function is() { +} \ No newline at end of file diff --git a/es2panda/test/parser/js/function-expression-arguments-expected.txt b/es2panda/test/parser/js/function-expression-arguments-expected.txt new file mode 100644 index 0000000000..1861431645 --- /dev/null +++ b/es2panda/test/parser/js/function-expression-arguments-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected reserved word in strict mode. [function-expression-arguments.js:3:20] diff --git a/es2panda/test/parser/js/function-expression-arguments.js b/es2panda/test/parser/js/function-expression-arguments.js new file mode 100644 index 0000000000..a8d93883a7 --- /dev/null +++ b/es2panda/test/parser/js/function-expression-arguments.js @@ -0,0 +1,4 @@ +'use strict' + +let foo = function arguments() { +} \ No newline at end of file diff --git a/es2panda/test/parser/js/function-expression-is-expected.txt b/es2panda/test/parser/js/function-expression-is-expected.txt new file mode 100644 index 0000000000..25297cebbb --- /dev/null +++ b/es2panda/test/parser/js/function-expression-is-expected.txt @@ -0,0 +1,145 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "StringLiteral", + "value": "use strict", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 8 + } + } + }, + "init": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "is", + "decorators": [], + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 22 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 3, + "column": 25 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 4, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/js/function-expression-is.js b/es2panda/test/parser/js/function-expression-is.js new file mode 100644 index 0000000000..6b90fce307 --- /dev/null +++ b/es2panda/test/parser/js/function-expression-is.js @@ -0,0 +1,4 @@ +'use strict' + +let foo = function is() { +} \ No newline at end of file -- Gitee From f3f568a5e6252da573178f33a5fe3fd7a9dbd22c Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Fri, 28 Oct 2022 01:44:40 +0000 Subject: [PATCH 22/59] Fix code check of switch Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5Y609?from=project-issue Signed-off-by: zhangrengao Change-Id: Id81c2d6b735fe460c985cbb7268a5bc47e0a674d --- es2panda/lexer/token/token.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/es2panda/lexer/token/token.cpp b/es2panda/lexer/token/token.cpp index ba04e5d974..61847be143 100644 --- a/es2panda/lexer/token/token.cpp +++ b/es2panda/lexer/token/token.cpp @@ -94,8 +94,7 @@ bool Token::IsReservedTypeName() const bool Token::IsJsStrictReservedWord() const { - switch (keywordType_) - { + switch (keywordType_) { case TokenType::KEYW_ARGUMENTS: case TokenType::KEYW_EVAL: case TokenType::KEYW_STATIC: -- Gitee From 90f263e3c9b43f7e9d0d91a77694a64a0b6593f5 Mon Sep 17 00:00:00 2001 From: chenqy930 Date: Thu, 13 Oct 2022 15:00:43 +0800 Subject: [PATCH 23/59] Adapt hotfix to new isa and some bugfixs Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5XPTY Signed-off-by: chenqy930 Change-Id: Ie08976cd7434511808b720f337f00a41a432de38 --- es2panda/util/hotfix.cpp | 44 +++++++++++++++++++--------------------- es2panda/util/hotfix.h | 7 ++++--- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/es2panda/util/hotfix.cpp b/es2panda/util/hotfix.cpp index 523247d352..ce21ad8158 100644 --- a/es2panda/util/hotfix.cpp +++ b/es2panda/util/hotfix.cpp @@ -29,7 +29,6 @@ namespace panda::es2panda::util { constexpr std::string_view ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER = "#"; const std::string EXTERNAL_ATTRIBUTE = "external"; -const uint32_t PATCH_ENV_VREG = 0; // reuse first param vreg const panda::panda_file::SourceLang SRC_LANG = panda::panda_file::SourceLang::ECMASCRIPT; void Hotfix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, @@ -75,14 +74,15 @@ void Hotfix::ValidateModuleInfo(const std::string &recordName, { auto it = originModuleInfo_->find(recordName); if (it == originModuleInfo_->end()) { - std::cerr << "Found new import/export expression in " << recordName << ", not supported!" << std::endl; + std::cerr << "[Patch] Found new import/export expression in " << recordName << ", not supported!" << std::endl; patchError_ = true; return; } auto hash = std::hash{}(ConvertLiteralToString(moduleBuffer)); if (std::to_string(hash) != it->second) { - std::cerr << "Found import/export expression changed in " << recordName << ", not supported!" << std::endl; + std::cerr << "[Patch] Found import/export expression changed in " << recordName << ", not supported!" << + std::endl; patchError_ = true; return; } @@ -93,6 +93,13 @@ bool Hotfix::IsAnonymousOrDuplicateNameFunction(const std::string &funcName) return funcName.find(ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER) != std::string::npos; } +int64_t Hotfix::GetLiteralIdxFromStringId(const std::string &stringId) +{ + auto recordPrefix = recordName_ + "_"; + auto idxStr = stringId.substr(recordPrefix.size()); + return std::atoi(idxStr.c_str()); +} + std::vector> Hotfix::GenerateFunctionAndClassHash(panda::pandasm::Function *func, LiteralBuffers &literalBuffers) { @@ -113,10 +120,10 @@ std::vector> Hotfix::GenerateFunctionAndClassHash ss << (ins.set_label ? "" : "\t") << ins.ToString("", true, func->GetTotalRegs()) << " "; if (ins.opcode == panda::pandasm::Opcode::CREATEARRAYWITHBUFFER || ins.opcode == panda::pandasm::Opcode::CREATEOBJECTWITHBUFFER) { - int64_t bufferIdx = std::get(ins.imms[0]); + int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[0]); ss << ExpandLiteral(bufferIdx, literalBuffers) << " "; } else if (ins.opcode == panda::pandasm::Opcode::DEFINECLASSWITHBUFFER) { - int64_t bufferIdx = std::get(ins.imms[0]); + int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[1]); std::string literalStr = ExpandLiteral(bufferIdx, literalBuffers); auto classHash = std::hash{}(literalStr); hashList.push_back(std::pair(ins.ids[0], classHash)); @@ -269,11 +276,6 @@ void Hotfix::HandleModifiedClasses(panda::pandasm::Program *prog) for (auto &cls: classMemberFunctions_) { for (auto &func: cls.second) { if (!prog->function_table.at(func).metadata->IsForeign()) { - if (func == cls.first) { - std::cerr << "Found class: " << cls.first << " constructor modified, not supported!" << std::endl; - patchError_ = true; - return; - } modifiedClassNames_.insert(cls.first); break; } @@ -306,12 +308,6 @@ void Hotfix::AddHeadAndTailInsForPatchFuncMain0(std::vector auto newFuncNum = long(ins.size() / 2); // each new function has 2 ins: define and store newLexenv.imms.emplace_back(newFuncNum); - panda::pandasm::Ins stLexenv; - stLexenv.opcode = pandasm::Opcode::STA; - stLexenv.regs.reserve(1); - stLexenv.regs.emplace_back(PATCH_ENV_VREG); - - ins.insert(ins.begin(), stLexenv); ins.insert(ins.begin(), newLexenv); ins.push_back(returnUndefine); } @@ -334,7 +330,6 @@ void Hotfix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFun if (IsFunctionOrClassDefineIns(funcDefineIns_[i])) { auto &name = funcDefineIns_[i].ids[0]; if (newFuncNames_.count(name)) { - funcDefineIns_[i].regs[0] = PATCH_ENV_VREG; patchMain0DefineIns.push_back(funcDefineIns_[i]); patchMain0DefineIns.push_back(funcDefineIns_[i + 1]); continue; @@ -350,6 +345,9 @@ void Hotfix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFun patchFuncMain0.ins = patchMain0DefineIns; patchFuncMain1.ins = patchMain1DefineIns; + + patchFuncMain0.return_type = panda::pandasm::Type("any", 0); + patchFuncMain1.return_type = panda::pandasm::Type("any", 0); } void Hotfix::Finalize(panda::pandasm::Program **prog) @@ -362,7 +360,7 @@ void Hotfix::Finalize(panda::pandasm::Program **prog) if (patchError_) { *prog = nullptr; - std::cerr << "Found unsupported change in file, will not generate patch!" << std::endl; + std::cerr << "[Patch] Found unsupported change in file, will not generate patch!" << std::endl; return; } @@ -381,7 +379,7 @@ bool Hotfix::CompareLexenv(const std::string &funcName, const compiler::PandaGen auto &lexenv = bytecodeInfo.lexenv; if (funcName != funcMain0_) { if (lexenv.size() != lexicalVarNameAndTypes.size()) { - std::cerr << "Found lexenv size changed, not supported!" << std::endl; + std::cerr << "[Patch] Found lexenv size changed, not supported!" << std::endl; patchError_ = true; return false; } @@ -389,14 +387,14 @@ bool Hotfix::CompareLexenv(const std::string &funcName, const compiler::PandaGen auto varName = std::string(variable.second.first); auto lexenvIter = lexenv.find(varName); if (lexenvIter == lexenv.end()) { - std::cerr << "Found new lex env added, not supported!" << std::endl; + std::cerr << "[Patch] Found new lex env added, not supported!" << std::endl; patchError_ = true; return false; } auto &lexInfo = lexenvIter->second; if (variable.first != lexInfo.first || variable.second.second != lexInfo.second) { - std::cerr << "Found new lex env changed(slot or type), not supported!" << std::endl; + std::cerr << "[Patch] Found new lex env changed(slot or type), not supported!" << std::endl; patchError_ = true; return false; } @@ -414,7 +412,7 @@ bool Hotfix::CompareClassHash(std::vector> &hashL auto classIter = classInfo.find(className); if (classIter != classInfo.end()) { if (classIter->second != std::to_string(hashList[i].second)) { - std::cerr << "Found class " << hashList[i].first << " changed, not supported!" << std::endl; + std::cerr << "[Patch] Found class " << hashList[i].first << " changed, not supported!" << std::endl; patchError_ = true; return false; } @@ -430,7 +428,7 @@ void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Functi auto originFunction = originFunctionInfo_->find(funcName); if (originFunction == originFunctionInfo_->end()) { if (IsAnonymousOrDuplicateNameFunction(funcName)) { - std::cerr << "Found new anonymous or duplicate name function " << funcName + std::cerr << "[Patch] Found new anonymous or duplicate name function " << funcName << " not supported!" << std::endl; patchError_ = true; return; diff --git a/es2panda/util/hotfix.h b/es2panda/util/hotfix.h index 0206acd1ec..36e06ddb51 100644 --- a/es2panda/util/hotfix.h +++ b/es2panda/util/hotfix.h @@ -50,9 +50,9 @@ public: classMemberFunctions_(allocator_.Adapter()) { originFunctionInfo_ = symbolTable_->GetOriginFunctionInfo(); originModuleInfo_ = symbolTable_->GetOriginModuleInfo(); - patchMain0_ = recordName_ + "patch_main_0"; - patchMain1_ = recordName_ + "patch_main_1"; - funcMain0_ = recordName_ + "func_main_0"; + patchMain0_ = recordName_ + ".patch_main_0"; + patchMain1_ = recordName_ + ".patch_main_1"; + funcMain0_ = recordName_ + ".func_main_0"; } void Finalize(panda::pandasm::Program **prog); @@ -87,6 +87,7 @@ private: void CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, LiteralBuffers &literalBuffers); std::vector GetLiteralMethods(int64_t bufferIdx, LiteralBuffers &literalBuffers); void HandleModifiedClasses(panda::pandasm::Program *prog); + int64_t GetLiteralIdxFromStringId(const std::string &stringId); std::mutex m_; uint32_t topScopeIdx_ {0}; -- Gitee From c9c1f9aa517127a9523357f422dd662ccf414827 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Thu, 13 Oct 2022 11:45:18 +0800 Subject: [PATCH 24/59] Fix declare as name and const as type reference Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5VHM2 Test: parser test, compiler test, test262 Signed-off-by: xucheng46 Change-Id: Idb19885c362cd78e8b108538cdea06ab88301ad3 --- es2panda/lexer/scripts/keywords.rb | 2 +- es2panda/parser/expressionParser.cpp | 3 +- es2panda/parser/parserImpl.cpp | 8 - es2panda/parser/parserImpl.h | 2 +- es2panda/parser/statementParser.cpp | 23 +- .../ts/test-as-expression3-expected.txt | 572 ++++++++++++++++++ .../test/parser/ts/test-as-expression3.ts | 21 + .../ts/test-as-expression4-expected.txt | 1 + .../test/parser/ts/test-as-expression4.ts | 17 + .../ts/test-as-expression5-expected.txt | 1 + .../test/parser/ts/test-as-expression5.ts | 17 + .../ts/test-as-expression6-expected.txt | 1 + .../test/parser/ts/test-as-expression6.ts | 17 + .../parser/ts/test-declare-name-expected.txt | 129 ++++ es2panda/test/parser/ts/test-declare-name.ts | 18 + .../ts/test-keyword-declare3-expected.txt | 2 +- es2panda/test/test_tsc_ignore_list.txt | 5 - 17 files changed, 812 insertions(+), 27 deletions(-) create mode 100644 es2panda/test/parser/ts/test-as-expression3-expected.txt create mode 100644 es2panda/test/parser/ts/test-as-expression3.ts create mode 100644 es2panda/test/parser/ts/test-as-expression4-expected.txt create mode 100644 es2panda/test/parser/ts/test-as-expression4.ts create mode 100644 es2panda/test/parser/ts/test-as-expression5-expected.txt create mode 100644 es2panda/test/parser/ts/test-as-expression5.ts create mode 100644 es2panda/test/parser/ts/test-as-expression6-expected.txt create mode 100644 es2panda/test/parser/ts/test-as-expression6.ts create mode 100644 es2panda/test/parser/ts/test-declare-name-expected.txt create mode 100644 es2panda/test/parser/ts/test-declare-name.ts diff --git a/es2panda/lexer/scripts/keywords.rb b/es2panda/lexer/scripts/keywords.rb index 00183eca59..8fdbfc3766 100644 --- a/es2panda/lexer/scripts/keywords.rb +++ b/es2panda/lexer/scripts/keywords.rb @@ -47,7 +47,7 @@ keywords = [ # keywords start with 'd' { "debugger" => ["TokenType::KEYW_DEBUGGER", "TokenType::KEYW_DEBUGGER"], - "declare" => ["TokenType::KEYW_DECLARE", "TokenType::KEYW_DECLARE"], + "declare" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_DECLARE"], "default" => ["TokenType::KEYW_DEFAULT", "TokenType::KEYW_DEFAULT"], "delete" => ["TokenType::KEYW_DELETE", "TokenType::KEYW_DELETE"], "do" => ["TokenType::KEYW_DO", "TokenType::KEYW_DO"], diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index 1ce216b74a..cb6d065fdf 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -522,7 +522,8 @@ ir::TSTypeAssertion *ParserImpl::ParseTsTypeAssertion(ExpressionParseFlags flags lexer::SourcePosition start = lexer_->GetToken().Start(); lexer_->NextToken(); // eat '<' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + TypeAnnotationParsingOptions options = + TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST; ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options); if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) { diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 999de8840a..905f1a5ed1 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -250,14 +250,6 @@ ir::TSTypeReference *ParserImpl::ParseTsConstExpression() lexer_->NextToken(); - if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA && - lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && - lexer_->GetToken().Type() != lexer::TokenType::EOS && - lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET && - !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE)) { - ThrowSyntaxError("Unexpected token."); - } - return typeReference; } diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 6398faa69a..fc1663e5e9 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -421,7 +421,7 @@ private: void CheckFunctionDeclaration(StatementParsingFlags flags); void CheckLabelledFunction(const ir::Statement *node); - void CheckDeclare(); + bool CheckDeclare(); bool IsLabelFollowedByIterationStatement(); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 51ba7e85f6..80cbcb8567 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -83,14 +83,11 @@ namespace panda::es2panda::parser { -void ParserImpl::CheckDeclare() +bool ParserImpl::CheckDeclare() { ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); - if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) { - ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context."); - } - + const auto startPos = lexer_->Save(); lexer_->NextToken(); // eat 'declare' switch (lexer_->GetToken().Type()) { case lexer::TokenType::KEYW_VAR: @@ -114,9 +111,17 @@ void ParserImpl::CheckDeclare() [[fallthrough]]; } default: { - ThrowSyntaxError("Unexpected token."); + lexer_->Rewind(startPos); + return false; } } + + if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) { + lexer_->Rewind(startPos); + ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context."); + } + + return true; } bool ParserImpl::IsLabelFollowedByIterationStatement() @@ -149,8 +154,7 @@ ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags) if (Extension() == ScriptExtension::TS) { if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { - CheckDeclare(); - isDeclare = true; + isDeclare = CheckDeclare(); } if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) { @@ -2402,8 +2406,7 @@ ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer: bool isTsModule = context_.IsTsModule(); if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { - CheckDeclare(); - isDeclare = true; + isDeclare = CheckDeclare(); } if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS && diff --git a/es2panda/test/parser/ts/test-as-expression3-expected.txt b/es2panda/test/parser/ts/test-as-expression3-expected.txt new file mode 100644 index 0000000000..92a8169e25 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression3-expected.txt @@ -0,0 +1,572 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 7 + } + } + }, + "init": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "const", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 7 + } + } + }, + "init": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "const", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 22 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a3", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 7 + } + } + }, + "init": { + "type": "ObjectExpression", + "properties": [ + { + "type": "Property", + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 11 + }, + "end": { + "line": 19, + "column": 12 + } + } + }, + "value": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "const", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 19, + "column": 11 + }, + "end": { + "line": 19, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 26 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a4", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 7 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 11 + }, + "end": { + "line": 20, + "column": 12 + } + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "const", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 11 + }, + "end": { + "line": 20, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 22 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a5", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 21, + "column": 7 + } + } + }, + "init": { + "type": "TSTypeAssertion", + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "const", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 11 + }, + "end": { + "line": 21, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 11 + }, + "end": { + "line": 21, + "column": 16 + } + } + }, + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 21, + "column": 20 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-as-expression3.ts b/es2panda/test/parser/ts/test-as-expression3.ts new file mode 100644 index 0000000000..0d584074ed --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression3.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a1 = 1 as const; +var a2 = (1 as const); +var a3 = {b : 1 as const}; +var a4 = [1 as const]; +var a5 = 1; diff --git a/es2panda/test/parser/ts/test-as-expression4-expected.txt b/es2panda/test/parser/ts/test-as-expression4-expected.txt new file mode 100644 index 0000000000..d1b6928df7 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression4-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [test-as-expression4.ts:17:20] diff --git a/es2panda/test/parser/ts/test-as-expression4.ts b/es2panda/test/parser/ts/test-as-expression4.ts new file mode 100644 index 0000000000..e226bfdc27 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression4.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a = 1 as const b; diff --git a/es2panda/test/parser/ts/test-as-expression5-expected.txt b/es2panda/test/parser/ts/test-as-expression5-expected.txt new file mode 100644 index 0000000000..01b1d76c59 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression5-expected.txt @@ -0,0 +1 @@ +SyntaxError: Primary expression expected [test-as-expression5.ts:17:20] diff --git a/es2panda/test/parser/ts/test-as-expression5.ts b/es2panda/test/parser/ts/test-as-expression5.ts new file mode 100644 index 0000000000..fe2c2086ba --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression5.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a = 1 as const?; diff --git a/es2panda/test/parser/ts/test-as-expression6-expected.txt b/es2panda/test/parser/ts/test-as-expression6-expected.txt new file mode 100644 index 0000000000..771c79d223 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression6-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [test-as-expression6.ts:17:19] diff --git a/es2panda/test/parser/ts/test-as-expression6.ts b/es2panda/test/parser/ts/test-as-expression6.ts new file mode 100644 index 0000000000..ed08243726 --- /dev/null +++ b/es2panda/test/parser/ts/test-as-expression6.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a = 1 as const.b; diff --git a/es2panda/test/parser/ts/test-declare-name-expected.txt b/es2panda/test/parser/ts/test-declare-name-expected.txt new file mode 100644 index 0000000000..aeae616792 --- /dev/null +++ b/es2panda/test/parser/ts/test-declare-name-expected.txt @@ -0,0 +1,129 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "declare", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "init": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 16 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 17 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "declare", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 8 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-declare-name.ts b/es2panda/test/parser/ts/test-declare-name.ts new file mode 100644 index 0000000000..d5f305f156 --- /dev/null +++ b/es2panda/test/parser/ts/test-declare-name.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +var declare = 1; +declare = 2; diff --git a/es2panda/test/parser/ts/test-keyword-declare3-expected.txt b/es2panda/test/parser/ts/test-keyword-declare3-expected.txt index 6d723d9d42..bda78d2974 100644 --- a/es2panda/test/parser/ts/test-keyword-declare3-expected.txt +++ b/es2panda/test/parser/ts/test-keyword-declare3-expected.txt @@ -1 +1 @@ -SyntaxError: Unexpected token. [test-keyword-declare3.ts:17:9] +SyntaxError: Unexpected token [test-keyword-declare3.ts:17:9] diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index 47c86b3e38..84265f688b 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -1,5 +1,4 @@ es2panda/test/TypeScript/tests/cases/compiler/ambientClassOverloadForFunction.ts -es2panda/test/TypeScript/tests/cases/compiler/assertionFunctionsCanNarrowByDiscriminant.ts es2panda/test/TypeScript/tests/cases/compiler/bom-utf16be.ts es2panda/test/TypeScript/tests/cases/compiler/classFunctionMerging.ts es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInType.ts @@ -9,7 +8,6 @@ es2panda/test/TypeScript/tests/cases/compiler/constructorOverloads5.ts es2panda/test/TypeScript/tests/cases/compiler/continueTarget3.ts es2panda/test/TypeScript/tests/cases/compiler/controlFlowCaching.ts es2panda/test/TypeScript/tests/cases/compiler/declarationEmitDestructuringOptionalBindingParametersInOverloads.ts -es2panda/test/TypeScript/tests/cases/compiler/declareIdentifierAsBeginningOfStatementExpression01.ts es2panda/test/TypeScript/tests/cases/compiler/discriminantsAndPrimitives.ts es2panda/test/TypeScript/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts es2panda/test/TypeScript/tests/cases/compiler/emitBundleWithShebang1.ts @@ -64,8 +62,6 @@ es2panda/test/TypeScript/tests/cases/conformance/es6/functionDeclarations/Functi es2panda/test/TypeScript/tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration2_es6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration4_es6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts -es2panda/test/TypeScript/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagNamedDeclare.ts -es2panda/test/TypeScript/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagNamedDeclareES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts es2panda/test/TypeScript/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTagsES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/templates/templateStringControlCharacterEscapes01.ts @@ -96,7 +92,6 @@ es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/Statements/C es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/parserUnicodeWhitespaceCharacter1.ts es2panda/test/TypeScript/tests/cases/conformance/scanner/ecmascript3/scannerES3NumericLiteral2.ts es2panda/test/TypeScript/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts -es2panda/test/TypeScript/tests/cases/conformance/types/literal/literalTypesAndDestructuring.ts es2panda/test/TypeScript/tests/cases/conformance/types/members/objectTypeWithStringNamedNumericProperty.ts es2panda/test/TypeScript/tests/cases/conformance/types/specifyingTypes/typeQueries/typeQueryWithReservedWords.ts es2panda/test/TypeScript/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts -- Gitee From 5df3591ca017a0f14b4363d047856906c0a10334 Mon Sep 17 00:00:00 2001 From: hufeng Date: Tue, 25 Oct 2022 14:48:11 +0800 Subject: [PATCH 25/59] Fix not restoring before CFG Signed-off-by: hufeng Change-Id: I45f2e5249176b924a123b377deb6415e2d0bd233 --- ts2panda/src/assemblyDumper.ts | 3 +- ts2panda/src/regAllocator.ts | 177 ++++++++++++---------------- ts2panda/tests/regAllocator.test.ts | 163 +++++++++++++++++++------ 3 files changed, 202 insertions(+), 141 deletions(-) diff --git a/ts2panda/src/assemblyDumper.ts b/ts2panda/src/assemblyDumper.ts index a11bc0b750..6b2fc9d793 100644 --- a/ts2panda/src/assemblyDumper.ts +++ b/ts2panda/src/assemblyDumper.ts @@ -82,7 +82,8 @@ export class AssemblyDumper { for (let i = 0; i < parametersCount; ++i) { let node = irNodes[i]; this.output += "\t"; - this.output += node.getMnemonic() + " v" + (node.operands[0]).num + ", a" + ((node.operands[0]).num) + "\n"; + let paramIdx = parametersCount - i - 1; + this.output += node.getMnemonic() + " v" + (node.operands[0]).num + ", a" + paramIdx + "\n"; } for (let i = parametersCount; i < irNodes.length; ++i) { diff --git a/ts2panda/src/regAllocator.ts b/ts2panda/src/regAllocator.ts index 9d5ac4f11f..790745246c 100644 --- a/ts2panda/src/regAllocator.ts +++ b/ts2panda/src/regAllocator.ts @@ -16,7 +16,7 @@ import { getRangeStartVregPos, isRangeInst } from "./base/util"; -import { CacheList } from "./base/vregisterCache"; +import { CacheList, VregisterCache } from "./base/vregisterCache"; import { DebugInfo } from "./debuginfo"; import { Format, @@ -28,21 +28,14 @@ import { } from "./irnodes"; import { PandaGen } from "./pandagen"; -const MAX_VREGA = 16; -const MAX_VREGB = 256; const MAX_VREGC = 65536; -interface VRegWithFlag { - vreg: VReg; - flag: boolean; // indicate whether it is used as a temporary register for spill -} - class RegAllocator { private newInsns: IRNode[] = []; private spills: VReg[] = []; + private spillId: number = 0; private vRegsId: number = 0; - private usedVreg: VRegWithFlag[] = []; - private tmpVreg: VRegWithFlag[] = []; + private needAdjust: boolean = false; constructor() { this.vRegsId = 0; @@ -51,42 +44,14 @@ class RegAllocator { allocIndexForVreg(vreg: VReg) { let num = this.getFreeVreg(); vreg.num = num; - this.usedVreg[num] = {vreg: vreg, flag: false}; } - findTmpVreg(level: number): VReg { - let iterCnts = Math.min(MAX_VREGB, this.usedVreg.length); - for (let i = 0; i < iterCnts; ++i) { - let value = this.usedVreg[i]; - if (value === undefined || value.flag) { - continue; - } - if (level === MAX_VREGA && value.vreg.num >= MAX_VREGA) { - throw new Error("no available tmp vReg from A"); - } - value.flag = true; - this.tmpVreg.push(value); - return value.vreg; - } - throw new Error("no available tmp vReg from B"); + getSpill(): VReg { + return this.spills[this.spillId++]; } - clearVregFlags(): void { - for (let v of this.tmpVreg) { - v.flag = false; - } - this.tmpVreg = []; - } - allocSpill(): VReg { - if (this.spills.length > 0) { - return this.spills.pop()!; - } - let v = new VReg(); - this.allocIndexForVreg(v); - return v; - } - freeSpill(v: VReg): void { - this.spills.push(v); + freeSpill(): void { + this.spillId = 0; } getFreeVreg(): number { @@ -112,48 +77,26 @@ class RegAllocator { return num; } - markVregNotAvailableAsTmp(vreg: VReg): void { - let num = vreg.num; - this.usedVreg[num].flag = true; - this.tmpVreg.push(this.usedVreg[num]); - } - doRealAdjustment(operands: OperandType[], format: Format, index: number, irNodes: IRNode[]) { let head: IRNode[] = []; let tail: IRNode[] = []; - let spills: VReg[] = []; - // mark all vreg used in the current insn as not valid for tmp register - for (let i = 0; i < operands.length; ++i) { - if (operands[i] instanceof VReg) { - this.markVregNotAvailableAsTmp(operands[i]); - } - } for (let j = 0; j < operands.length; ++j) { if (operands[j] instanceof VReg) { let vOrigin = operands[j]; if (vOrigin.num >= (1 << format[j][1])) { - let spill = this.allocSpill(); - spills.push(spill); - let vTmp; - try { - vTmp = this.findTmpVreg(1 << format[j][1]); - } catch { - throw Error("no available tmp vReg"); - } - head.push(new Mov(spill, vTmp)); - operands[j] = vTmp; + let spill = this.getSpill(); + operands[j] = spill; if (format[j][0] == OperandKind.SrcVReg) { - head.push(new Mov(vTmp, vOrigin)); + head.push(new Mov(spill, vOrigin)); } else if (format[j][0] == OperandKind.DstVReg) { - tail.push(new Mov(vOrigin, vTmp)) + tail.push(new Mov(vOrigin, spill)) } else if (format[j][0] == OperandKind.SrcDstVReg) { - head.push(new Mov(vTmp, vOrigin)); - tail.push(new Mov(vOrigin, vTmp)) + head.push(new Mov(spill, vOrigin)); + tail.push(new Mov(vOrigin, spill)) } else { // here we do nothing } - tail.push(new Mov(vTmp, spill)); } } } @@ -163,11 +106,7 @@ class RegAllocator { DebugInfo.copyDebugInfo(irNodes[index], tail); this.newInsns.push(...head, irNodes[index], ...tail); - - for (let j = spills.length - 1; j >= 0; --j) { - this.freeSpill(spills[j]); - } - this.clearVregFlags(); + this.freeSpill(); } checkDynRangeInstruction(irNodes: IRNode[], index: number): boolean { @@ -179,8 +118,6 @@ class RegAllocator { 1. "CalliDynRange 4, v255" is a valid insn, there is no need for all 4 registers numbers to be less than 255, it is also similar for NewobjDyn 2. we do not need to mark any register to be invalid for tmp register, since no other register is used in calli.dyn.range - 3. if v.num is bigger than 255, it means all register less than 255 has been already used, they should have been pushed - into usedVreg */ if ((operands[rangeRegOffset]).num >= level) { // needs to be adjusted. @@ -208,37 +145,23 @@ class RegAllocator { adjustDynRangeInstruction(irNodes: IRNode[], index: number) { let head: IRNode[] = []; - let tail: IRNode[] = []; - let spills: VReg[] = []; let operands = irNodes[index].operands; /* exclude operands that are not require consecutive */ let rangeRegOffset = getRangeStartVregPos(irNodes[index]); let regNums = operands.length - getRangeStartVregPos(irNodes[index]); - let level = 1 << (irNodes[index].getFormats())[0][rangeRegOffset][1]; - let tmp = this.findTmpVreg(level); - for (let i = 0; i < regNums; i++) { - let spill = this.allocSpill(); - spills.push(spill); - - /* We need to make sure that the register input in the .range instruction is continuous(small to big). */ - head.push(new Mov(spill, this.usedVreg[tmp.num + i].vreg)); - head.push(new Mov(this.usedVreg[tmp.num + i].vreg, operands[i + rangeRegOffset])); - operands[i + rangeRegOffset] = this.usedVreg[tmp.num + i].vreg; - tail.push(new Mov(this.usedVreg[tmp.num + i].vreg, spill)); + let spill = this.getSpill(); + head.push(new Mov(spill, operands[i + rangeRegOffset])); + operands[i + rangeRegOffset] = spill; } // for debuginfo DebugInfo.copyDebugInfo(irNodes[index], head); - DebugInfo.copyDebugInfo(irNodes[index], tail); - this.newInsns.push(...head, irNodes[index], ...tail); - for (let i = spills.length - 1; i >= 0; --i) { - this.freeSpill(spills[i]); - } - this.clearVregFlags(); + this.newInsns.push(...head, irNodes[index]); + this.freeSpill(); } adjustInstructionsIfNeeded(irNodes: IRNode[]): void { @@ -275,13 +198,7 @@ class RegAllocator { return this.vRegsId; } - run(pandaGen: PandaGen): void { - let irNodes = pandaGen.getInsns(); - let locals = pandaGen.getLocals(); - let temps = pandaGen.getTemps(); - let cache = pandaGen.getVregisterCache(); - let parametersCount = pandaGen.getParametersCount(); - // don't mess up allocation order + allocIndexForVregs(locals: VReg[], temps: VReg[], cache: VregisterCache): void { for (let i = 0; i < locals.length; ++i) { this.allocIndexForVreg(locals[i]); } @@ -294,6 +211,60 @@ class RegAllocator { this.allocIndexForVreg(cacheItem.getCache()); } } + } + + allocSpillPool(irNodes: IRNode[]): void { + let spillCount: number = 0; + for (let i = 0; i < irNodes.length; ++i) { + let operands = irNodes[i].operands; + let formats = irNodes[i].getFormats(); + if (isRangeInst(irNodes[i])) { + let rangeRegOffset = getRangeStartVregPos(irNodes[i]); + spillCount = Math.max(spillCount, operands.length - rangeRegOffset); + + let level = 1 << (irNodes[i].getFormats())[0][rangeRegOffset][1]; + if ((operands[rangeRegOffset]).num >= level) { + this.needAdjust = true; + } + continue; + } + + let min = operands.length; + spillCount = Math.max(spillCount, min); + for (let j = 0; j < formats.length; ++j) { + let num = this.getNumOfInvalidVregs(operands, formats[j]); + if (num < min) { + min = num; + } + } + if (min > 0) { + this.needAdjust = true; + } + } + + if (this.needAdjust) { + this.vRegsId = 0; + while (spillCount--) { + let spill = new VReg(); + this.allocIndexForVreg(spill); + this.spills.push(spill); + } + } + } + + run(pandaGen: PandaGen): void { + let irNodes = pandaGen.getInsns(); + let locals = pandaGen.getLocals(); + let temps = pandaGen.getTemps(); + let cache = pandaGen.getVregisterCache(); + let parametersCount = pandaGen.getParametersCount(); + + this.allocIndexForVregs(locals, temps, cache); + this.allocSpillPool(irNodes); + if (this.needAdjust) { + // assign index to Vregs again + this.allocIndexForVregs(locals, temps, cache); + } this.adjustInstructionsIfNeeded(irNodes); for (let i = 0; i < parametersCount; ++i) { let v = new VReg(); diff --git a/ts2panda/tests/regAllocator.test.ts b/ts2panda/tests/regAllocator.test.ts index b20940b14b..185ebd3594 100644 --- a/ts2panda/tests/regAllocator.test.ts +++ b/ts2panda/tests/regAllocator.test.ts @@ -19,19 +19,22 @@ import * as ts from "typescript"; import { Callrange, Returnundefined, - Sttoglobalrecord, - Tryldglobalbyname, Imm, IRNode, + Jmp, + Label, Ldai, Lda, + Ldglobalvar, + Mov, Sta, + Throw, VReg } from "../src/irnodes"; import { PandaGen } from "../src/pandagen"; import { CacheExpander } from "../src/pass/cacheExpander"; import { RegAlloc } from "../src/regAllocator"; -import { basicChecker, checkInstructions, compileAllSnippet } from "./utils/base"; +import { basicChecker, checkInstructions, compileAllSnippet, SnippetCompiler } from "./utils/base"; import { creatAstFromSnippet } from "./utils/asthelper"; function checkRegisterNumber(left: IRNode, right: IRNode): boolean { @@ -55,32 +58,46 @@ function checkRegisterNumber(left: IRNode, right: IRNode): boolean { return true; } describe("RegAllocator", function () { - it("make spill for Src register", function () { - let string: string = ""; + it("make spill for Dst register & Src register", function () { + let string = "function test() {"; for (let i = 0; i < 256; ++i) { string += "let a" + i + " = " + i + ";"; } - string += "a255;"; + string += "a255;}"; + + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(string, [new CacheExpander(), new RegAlloc()]); + let insns = snippetCompiler.getPandaGenByName("UnitTest.test").getInsns(); - let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]); - let insns = pgs[0].getInsns(); IRNode.pg = new PandaGen("", creatAstFromSnippet(""), 0, undefined); - IRNode.pg.updateIcSize(252); + IRNode.pg.updateIcSize(0); + + let v = []; + for (let i = 0; i < 260; ++i) { + v[i] = new VReg(); + v[i].num = i; + } let expected: IRNode[] = [ new Ldai(new Imm(252)), - new Sttoglobalrecord(new Imm(0), 'a252'), + new Sta(v[0]), + new Mov(v[256], v[0]), new Ldai(new Imm(253)), - new Sttoglobalrecord(new Imm(1), 'a253'), + new Sta(v[0]), + new Mov(v[257], v[0]), new Ldai(new Imm(254)), - new Sttoglobalrecord(new Imm(2), 'a254'), + new Sta(v[0]), + new Mov(v[258], v[0]), new Ldai(new Imm(255)), - new Sttoglobalrecord(new Imm(3), 'a255'), - new Tryldglobalbyname(new Imm(4), 'a255'), + new Sta(v[0]), + new Mov(v[259], v[0]), + // load a255 + new Mov(v[0], v[259]), + new Lda(v[0]), new Returnundefined() ] - expect(checkInstructions(insns.slice(insns.length - 10), expected, checkRegisterNumber)).to.be.true; + expect(checkInstructions(insns.slice(insns.length - 15), expected, checkRegisterNumber)).to.be.true; }); it("make spill for SrcDst register", function () { @@ -95,41 +112,113 @@ describe("RegAllocator", function () { but in case later 16 might be changed to 8, then spill operation will be needed in some cases. this testcase is designed for 8bits constraints. */ - let string = ""; + let string = "function test() {"; for (let i = 0; i < 256; ++i) { string += "let a" + i + " = " + i + ";"; } - string += "call(a252, a253, a254, a255);"; - let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]); - let insns = pgs[0].getInsns(); + string += "test(a252, a253, a254, a255);}"; + + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(string, [new CacheExpander(), new RegAlloc()]); + let insns = snippetCompiler.getPandaGenByName("UnitTest.test").getInsns(); + IRNode.pg = new PandaGen("", creatAstFromSnippet(""), 0, undefined); - IRNode.pg.updateIcSize(252); + IRNode.pg.updateIcSize(0); let v = []; - for (let i = 0; i < 8; ++i) { + for (let i = 0; i < 268; ++i) { v[i] = new VReg(); v[i].num = i; } let expected = [ new Ldai(new Imm(252)), - new Sttoglobalrecord(new Imm(252), 'a252'), + new Sta(v[0]), + new Mov(v[259], v[0]), + new Ldai(new Imm(253)), + new Sta(v[0]), + new Mov(v[260], v[0]), + new Ldai(new Imm(254)), + new Sta(v[0]), + new Mov(v[261], v[0]), + new Ldai(new Imm(255)), + new Sta(v[0]), + new Mov(v[262], v[0]), + new Ldglobalvar(new Imm(0), "test"), + new Sta(v[0]), + new Mov(v[263], v[0]), + // call test with [a252, a253, a254, a255] + new Mov(v[0], v[259]), + new Lda(v[0]), + new Sta(v[0]), + new Mov(v[264], v[0]), + new Mov(v[0], v[260]), + new Lda(v[0]), + new Sta(v[0]), + new Mov(v[265], v[0]), + new Mov(v[0], v[261]), + new Lda(v[0]), + new Sta(v[0]), + new Mov(v[266], v[0]), + new Mov(v[0], v[262]), + new Lda(v[0]), + new Sta(v[0]), + new Mov(v[267], v[0]), + new Mov(v[0], v[263]), + new Lda(v[0]), + new Mov(v[0], v[264]), + new Mov(v[1], v[265]), + new Mov(v[2], v[266]), + new Mov(v[3], v[267]), + new Callrange(new Imm(1), new Imm(4), [v[0], v[1], v[2], v[3]]), + new Returnundefined(), + ]; + + expect(checkInstructions(insns.slice(insns.length - 39), expected, checkRegisterNumber)).to.be.true; + }); + + it("make spill for control-flow change", function () { + let string = "function test() {"; + for (let i = 0; i < 256; ++i) { + string += "let a" + i + " = " + i + ";"; + } + string += `try { throw a0; } catch { a0 }};`; + + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(string, [new CacheExpander(), new RegAlloc()]); + let insns = snippetCompiler.getPandaGenByName("UnitTest.test").getInsns(); + + IRNode.pg = new PandaGen("", creatAstFromSnippet(""), 0, undefined); + IRNode.pg.updateIcSize(0); + let v = []; + for (let i = 0; i < 261; ++i) { + v[i] = new VReg(); + v[i].num = i; + } + let tryBeginLabel = new Label(); + let tryEndLabel = new Label(); + let catchBeginLabel = new Label(); + let catchEndLabel = new Label(); + + let expected = [ + new Ldai(new Imm(252)), + new Sta(v[0]), + new Mov(v[256], v[0]), new Ldai(new Imm(253)), - new Sttoglobalrecord(new Imm(253), 'a253'), + new Sta(v[0]), + new Mov(v[257], v[0]), new Ldai(new Imm(254)), - new Sttoglobalrecord(new Imm(254), 'a254'), + new Sta(v[0]), + new Mov(v[258], v[0]), new Ldai(new Imm(255)), - new Sttoglobalrecord(new Imm(256), 'a255'), - new Tryldglobalbyname(new Imm(257), 'call'), - new Sta(v[3]), - new Tryldglobalbyname(new Imm(258), 'a252'), - new Sta(v[4]), - new Tryldglobalbyname(new Imm(259), 'a253'), - new Sta(v[5]), - new Tryldglobalbyname(new Imm(260), 'a254'), - new Sta(v[6]), - new Tryldglobalbyname(new Imm(261), 'a255'), - new Sta(v[7]), - new Lda(v[3]), - new Callrange(new Imm(255), new Imm(4), [v[4], v[5], v[6], v[7]]), + new Sta(v[0]), + new Mov(v[259], v[0]), + tryBeginLabel, + new Lda(v[4]), + new Throw(), + tryEndLabel, + new Jmp(catchEndLabel), + catchBeginLabel, + new Lda(v[4]), + catchEndLabel, new Returnundefined(), ]; -- Gitee From cb2184d335ae1801ef4a82500cd6599c2d81505f Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Fri, 28 Oct 2022 09:10:55 +0000 Subject: [PATCH 26/59] Support Nullish Coalesce on es2abc Issue:I5YAQB Signed-off-by: ctw-ian Change-Id: I9c4721ae3b5ddfb7778da12774a1d964df3a1e2c --- es2panda/compiler/core/pandagen.cpp | 10 ++++++++++ es2panda/compiler/core/pandagen.h | 1 + es2panda/ir/expressions/binaryExpression.cpp | 20 +++++++++++-------- .../nullishCoalesce-expected.txt | 3 +++ .../js/binaryExpression/nullishCoalesce.js | 9 +++++++++ 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt create mode 100644 es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 3488d439f9..ed81f39bda 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1071,6 +1071,16 @@ void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) sa_.Emit(node, target); } +void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target) +{ + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + LoadConst(node, Constant::JS_NULL); + ra_.Emit(node, 0, tmp); + sa_.Emit(node, target); +} + void PandaGen::EmitThrow(const ir::AstNode *node) { sa_.Emit(node); diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index cdc5a69bc9..02f17f126c 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -313,6 +313,7 @@ public: void BranchIfNotTrue(const ir::AstNode *node, class Label *target); void BranchIfFalse(const ir::AstNode *node, class Label *target); void BranchIfNotFalse(const ir::AstNode *node, class Label *target); + void BranchIfStrictNull(const ir::AstNode *node, class Label *target); void EmitThrow(const ir::AstNode *node); void EmitRethrow(const ir::AstNode *node); diff --git a/es2panda/ir/expressions/binaryExpression.cpp b/es2panda/ir/expressions/binaryExpression.cpp index 58fafd3d1a..526685b453 100644 --- a/es2panda/ir/expressions/binaryExpression.cpp +++ b/es2panda/ir/expressions/binaryExpression.cpp @@ -43,13 +43,9 @@ void BinaryExpression::CompileLogical(compiler::PandaGen *pg) const compiler::RegScope rs(pg); compiler::VReg lhs = pg->AllocReg(); - if (operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING) { - // TODO(parser): Nullish Coalesce - compiler::PandaGen::Unimplemented(); - } - ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || - operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR || + operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING); auto *skipRight = pg->AllocLabel(); auto *endLabel = pg->AllocLabel(); @@ -59,9 +55,17 @@ void BinaryExpression::CompileLogical(compiler::PandaGen *pg) const if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { pg->BranchIfFalse(this, skipRight); - } else { - ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + } else if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR) { pg->BranchIfTrue(this, skipRight); + } else { + ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING); + auto *nullish = pg->AllocLabel(); + // if lhs === null + pg->BranchIfStrictNull(this, nullish); + pg->LoadAccumulator(this, lhs); + // if lhs === undefined + pg->BranchIfStrictNotUndefined(this, skipRight); + pg->SetLabel(this, nullish); } // left is true/false(and/or) then right -> acc diff --git a/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt new file mode 100644 index 0000000000..0429fae9e5 --- /dev/null +++ b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt @@ -0,0 +1,3 @@ +2 +4 +5 diff --git a/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js new file mode 100644 index 0000000000..45d895e52b --- /dev/null +++ b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js @@ -0,0 +1,9 @@ +let a = 2; +let b = a ?? 3; +print(b); +a = null; +b = a ?? 4; +print(b); +a = undefined; +b = a ?? 5; +print(b); \ No newline at end of file -- Gitee From 295a143585bdef16f407d2372c6756232d382774 Mon Sep 17 00:00:00 2001 From: zhangrengao Date: Fri, 28 Oct 2022 09:17:01 +0000 Subject: [PATCH 27/59] Fix special character of template literal Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5YATR?from=project-issue Test: test262 of es2abc, parser, compiler Signed-off-by: zhangrengao Change-Id: I8a302e2bc75a732e5661389112436bd1424431c6 --- es2panda/ir/expressions/templateLiteral.cpp | 4 ++-- .../literals/special-character-expected.txt | 9 +++++++++ .../js/language/literals/special-character.js | 13 +++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 es2panda/test/compiler/js/language/literals/special-character-expected.txt create mode 100644 es2panda/test/compiler/js/language/literals/special-character.js diff --git a/es2panda/ir/expressions/templateLiteral.cpp b/es2panda/ir/expressions/templateLiteral.cpp index 1a66c3b81a..202b21dd3b 100644 --- a/es2panda/ir/expressions/templateLiteral.cpp +++ b/es2panda/ir/expressions/templateLiteral.cpp @@ -43,7 +43,7 @@ void TemplateLiteral::Compile(compiler::PandaGen *pg) const auto quasisIt = quasis_.begin(); auto expressionIt = expressions_.begin(); - pg->LoadAccumulatorString(this, (*quasisIt)->Raw()); + pg->LoadAccumulatorString(this, (*quasisIt)->Cooked()); quasisIt++; @@ -58,7 +58,7 @@ void TemplateLiteral::Compile(compiler::PandaGen *pg) const if (isQuais) { pg->StoreAccumulator(*quasisIt, lhs); - pg->LoadAccumulatorString(this, (*quasisIt)->Raw()); + pg->LoadAccumulatorString(this, (*quasisIt)->Cooked()); node = *quasisIt; quasisIt++; diff --git a/es2panda/test/compiler/js/language/literals/special-character-expected.txt b/es2panda/test/compiler/js/language/literals/special-character-expected.txt new file mode 100644 index 0000000000..c54b773db3 --- /dev/null +++ b/es2panda/test/compiler/js/language/literals/special-character-expected.txt @@ -0,0 +1,9 @@ +test + +test + +test +test' +test" +test? +test diff --git a/es2panda/test/compiler/js/language/literals/special-character.js b/es2panda/test/compiler/js/language/literals/special-character.js new file mode 100644 index 0000000000..7ced4fee80 --- /dev/null +++ b/es2panda/test/compiler/js/language/literals/special-character.js @@ -0,0 +1,13 @@ +function test() { + let a = "test\n"; + print(a); + let b = "test"; + print(`${b}\n`); + print(`${b}\t`); + print(`${b}\'`); + print(`${b}\"`); + print(`${b}\?`); + print(`${b}\0`); +} + +test(); \ No newline at end of file -- Gitee From f7d3a584477cc5758ffa4e29b1748e7444a15b02 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 17 Oct 2022 17:53:34 +0800 Subject: [PATCH 28/59] Distinguish Getter/Setter from general functions Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5W3HB Signed-off-by: huangyu Change-Id: I69463d3746f161025e4dfd4e04b134857af9817b --- .../expect/types/rest/objectRestParameter.txt | 2 +- ts2panda/src/base/typeSystem.ts | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/testTs/expect/types/rest/objectRestParameter.txt b/testTs/expect/types/rest/objectRestParameter.txt index d3582019b9..f1d5ac1eb9 100644 --- a/testTs/expect/types/rest/objectRestParameter.txt +++ b/testTs/expect/types/rest/objectRestParameter.txt @@ -3,7 +3,7 @@ {'lb': [{'t': 2, 'v': 1}, {'t': 2, 'v': 0}, {'t': 25, 'v': 0}, {'t': 2, 'v': 0}, {'t': 2, 'v': 0}, {'t': 2, 'v': 2}, {'t': 5, 'v': 'm'}, {'t': 24, 'v': '_4'}, {'t': 5, 'v': 'p'}, {'t': 24, 'v': '_6'}, {'t': 2, 'v': 0}, {'t': 2, 'v': 0}], 'k': '_3'} {'lb': [{'t': 2, 'v': 3}, {'t': 2, 'v': 0}, {'t': 5, 'v': 'm'}, {'t': 2, 'v': 0}, {'t': 2, 'v': 1}, {'t': 24, 'v': '_5'}, {'t': 25, 'v': 3}], 'k': '_4'} {'lb': [{'t': 2, 'v': 6}, {'t': 2, 'v': 2}, {'t': 5, 'v': 'a'}, {'t': 25, 'v': 1}, {'t': 5, 'v': 'b'}, {'t': 25, 'v': 4}], 'k': '_5'} -{'lb': [{'t': 2, 'v': 3}, {'t': 2, 'v': 0}, {'t': 5, 'v': 'p'}, {'t': 2, 'v': 0}, {'t': 2, 'v': 1}, {'t': 24, 'v': '_7'}, {'t': 25, 'v': 0}], 'k': '_6'} +{'lb': [{'t': 2, 'v': 3}, {'t': 2, 'v': 32}, {'t': 5, 'v': 'p'}, {'t': 2, 'v': 0}, {'t': 2, 'v': 1}, {'t': 24, 'v': '_7'}, {'t': 25, 'v': 0}], 'k': '_6'} {'lb': [{'t': 2, 'v': 6}, {'t': 2, 'v': 2}, {'t': 5, 'v': 'a'}, {'t': 25, 'v': 1}, {'t': 5, 'v': 'b'}, {'t': 25, 'v': 4}], 'k': '_7'} {'lb': [{'t': 2, 'v': 2}, {'t': 24, 'v': '_3'}], 'k': '_8'} {'lb': [{'t': 2, 'v': 3}, {'t': 2, 'v': 0}, {'t': 5, 'v': 'foobar'}, {'t': 2, 'v': 0}, {'t': 2, 'v': 1}, {'t': 25, 'v': 0}, {'t': 25, 'v': 0}], 'k': '_9'} diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index cc06969f49..331e4f9ded 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -129,9 +129,9 @@ export enum ModifierAbstract { } export enum Modifier { - STATIC = 4, - ASYNC = 8, - ASTERISK = 16 + STATIC = 1 << 2, + ASYNC = 1 << 3, + ASTERISK = 1 << 4 } export enum ModifierReadonly { @@ -145,6 +145,11 @@ export enum AccessFlag { PROTECTED } +export enum GetOrSetAccessorFlag { + FALSE = 0, // Not GetAccessor and SetAccessor + TRUE = 1 << 5 // GetAccessor or SetAccessor +} + type ClassMemberFunction = ts.MethodDeclaration | ts.ConstructorDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration; @@ -515,12 +520,16 @@ export class FunctionType extends BaseType { returnType: number = PrimitiveType.ANY; typeIndex: number; shiftedTypeIndex: number; + getOrSetAccessorFlag: GetOrSetAccessorFlag = GetOrSetAccessorFlag.FALSE; constructor(funcNode: ts.FunctionLikeDeclaration | ts.MethodSignature, builtinTypeIdx: number = undefined) { super(); let res = this.calculateIndex(builtinTypeIdx); this.typeIndex = res.typeIndex; this.shiftedTypeIndex = res.shiftedTypeIndex; + if (funcNode.kind == ts.SyntaxKind.GetAccessor || funcNode.kind == ts.SyntaxKind.SetAccessor) { + this.getOrSetAccessorFlag = GetOrSetAccessorFlag.TRUE; + } // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type @@ -600,7 +609,7 @@ export class FunctionType extends BaseType { 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 + this.modifiers)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag + this.modifiers + this.getOrSetAccessorFlag)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); if (this.containThisParam) { funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, 1)); // marker for having 'this' param -- Gitee From 8fd0db3336c7be8b6f8342425abc28c0671edb35 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Thu, 13 Oct 2022 22:44:36 +0800 Subject: [PATCH 29/59] Enable TypePredicate in class method and definite in variable Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5VMHG Test: parser tests, compiler tests, test262 Signed-off-by: xucheng46 Change-Id: I836794ccc40b6438c57f4297ce942309b306f037 --- es2panda/ir/statements/variableDeclarator.cpp | 5 +- es2panda/ir/statements/variableDeclarator.h | 12 + es2panda/parser/expressionParser.cpp | 8 +- es2panda/parser/statementParser.cpp | 7 + .../ts/test-class-definiton20-expected.txt | 665 ++++++++++++++++++ .../test/parser/ts/test-class-definiton20.ts | 29 + .../ts/test-definite-variable-expected.txt | 74 ++ .../test/parser/ts/test-definite-variable.ts | 17 + es2panda/test/test_tsc_ignore_list.txt | 4 - 9 files changed, 815 insertions(+), 6 deletions(-) create mode 100644 es2panda/test/parser/ts/test-class-definiton20-expected.txt create mode 100644 es2panda/test/parser/ts/test-class-definiton20.ts create mode 100644 es2panda/test/parser/ts/test-definite-variable-expected.txt create mode 100644 es2panda/test/parser/ts/test-definite-variable.ts diff --git a/es2panda/ir/statements/variableDeclarator.cpp b/es2panda/ir/statements/variableDeclarator.cpp index ef3fb7d5bc..1c4d57bae7 100644 --- a/es2panda/ir/statements/variableDeclarator.cpp +++ b/es2panda/ir/statements/variableDeclarator.cpp @@ -40,7 +40,10 @@ void VariableDeclarator::Iterate(const NodeTraverser &cb) const void VariableDeclarator::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "VariableDeclarator"}, {"id", id_}, {"init", AstDumper::Nullable(init_)}}); + dumper->Add({{"type", "VariableDeclarator"}, + {"id", id_}, + {"definite", AstDumper::Optional(definite_)}, + {"init", AstDumper::Nullable(init_)}}); } void VariableDeclarator::Compile(compiler::PandaGen *pg) const diff --git a/es2panda/ir/statements/variableDeclarator.h b/es2panda/ir/statements/variableDeclarator.h index 4c695dfbf2..02d8cc2933 100644 --- a/es2panda/ir/statements/variableDeclarator.h +++ b/es2panda/ir/statements/variableDeclarator.h @@ -64,6 +64,16 @@ public: return id_; } + bool Definite() const + { + return definite_; + } + + void SetDefinite(bool definite) + { + definite_ = definite; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; @@ -73,6 +83,8 @@ public: private: Expression *id_; Expression *init_; + // TODO(xucheng): don't use now, it will be used in type checker later + bool definite_; }; } // namespace panda::es2panda::ir diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index cb6d065fdf..5ac12ec0d8 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -564,7 +564,9 @@ ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterLi ir::Expression *returnTypeAnnotation = nullptr; if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { lexer_->NextToken(); // eat ':' + options |= TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; returnTypeAnnotation = ParseTsTypeAnnotation(&options); + options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; } if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { @@ -580,7 +582,9 @@ ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterLi ir::Expression *returnTypeAnnotation = nullptr; if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { lexer_->NextToken(); // eat ':' + options |= TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; returnTypeAnnotation = ParseTsTypeAnnotation(&options); + options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; } if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { @@ -615,8 +619,10 @@ ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterLi if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { lexer_->NextToken(); // eat ':' - options = ~TypeAnnotationParsingOptions::THROW_ERROR; + options &= ~TypeAnnotationParsingOptions::THROW_ERROR; + options |= TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; returnTypeAnnotation = ParseTsTypeAnnotation(&options); + options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE; } if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 80cbcb8567..6c8250593d 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -1925,7 +1925,12 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags } } + bool isDefinite = false; if (Extension() == ScriptExtension::TS) { + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { + lexer_->NextToken(); // eat '!' + isDefinite = true; + } if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { lexer_->NextToken(); // eat ':' TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; @@ -1953,6 +1958,8 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags declarator->SetRange({startLoc, endLoc}); } + declarator->SetDefinite(isDefinite); + std::vector bindings = util::Helpers::CollectBindingNames(init); for (const auto *binding : bindings) { diff --git a/es2panda/test/parser/ts/test-class-definiton20-expected.txt b/es2panda/test/parser/ts/test-class-definiton20-expected.txt new file mode 100644 index 0000000000..d2b8028ba7 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton20-expected.txt @@ -0,0 +1,665 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "value": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "TSTypePredicate", + "parameterName": { + "type": "TSThisType", + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 18 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "asserts": false, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "value": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 21 + } + } + } + ], + "returnType": { + "type": "TSTypePredicate", + "parameterName": { + "type": "TSThisType", + "loc": { + "start": { + "line": 22, + "column": 24 + }, + "end": { + "line": 22, + "column": 28 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 22, + "column": 32 + }, + "end": { + "line": 22, + "column": 38 + } + } + }, + "asserts": false, + "loc": { + "start": { + "line": 22, + "column": 24 + }, + "end": { + "line": 22, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 42 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 6 + } + } + }, + "value": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 25 + } + } + } + ], + "returnType": { + "type": "TSTypePredicate", + "parameterName": { + "type": "TSThisType", + "loc": { + "start": { + "line": 26, + "column": 29 + }, + "end": { + "line": 26, + "column": 33 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 26, + "column": 37 + }, + "end": { + "line": 26, + "column": 43 + } + } + }, + "asserts": false, + "loc": { + "start": { + "line": 26, + "column": 29 + }, + "end": { + "line": 26, + "column": 43 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 47 + }, + "end": { + "line": 28, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 28, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 28, + "column": 6 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 28, + "column": 6 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 30, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-class-definiton20.ts b/es2panda/test/parser/ts/test-class-definiton20.ts new file mode 100644 index 0000000000..cc1c9ec683 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton20.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + a = () : this is number => { + return false; + } + + b = (b : number) : this is number => { + return false; + } + + c = (...c : number[]) : this is number => { + return false; + } +} diff --git a/es2panda/test/parser/ts/test-definite-variable-expected.txt b/es2panda/test/parser/ts/test-definite-variable-expected.txt new file mode 100644 index 0000000000..f3f69098b6 --- /dev/null +++ b/es2panda/test/parser/ts/test-definite-variable-expected.txt @@ -0,0 +1,74 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 6 + } + } + }, + "definite": true, + "init": null, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 6 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-definite-variable.ts b/es2panda/test/parser/ts/test-definite-variable.ts new file mode 100644 index 0000000000..409503959d --- /dev/null +++ b/es2panda/test/parser/ts/test-definite-variable.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a!:number; diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index 84265f688b..7212fc2461 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -8,7 +8,6 @@ es2panda/test/TypeScript/tests/cases/compiler/constructorOverloads5.ts es2panda/test/TypeScript/tests/cases/compiler/continueTarget3.ts es2panda/test/TypeScript/tests/cases/compiler/controlFlowCaching.ts es2panda/test/TypeScript/tests/cases/compiler/declarationEmitDestructuringOptionalBindingParametersInOverloads.ts -es2panda/test/TypeScript/tests/cases/compiler/discriminantsAndPrimitives.ts es2panda/test/TypeScript/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts es2panda/test/TypeScript/tests/cases/compiler/emitBundleWithShebang1.ts es2panda/test/TypeScript/tests/cases/compiler/exportAsNamespace.d.ts @@ -37,7 +36,6 @@ es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringFo es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPattern2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPatternDefaultValues2.ts -es2panda/test/TypeScript/tests/cases/compiler/taggedTemplateStringWithSymbolExpression01.ts es2panda/test/TypeScript/tests/cases/compiler/withStatementInternalComments.ts es2panda/test/TypeScript/tests/cases/conformance/async/es2017/asyncAwait_es2017.ts es2panda/test/TypeScript/tests/cases/conformance/classes/members/privateNames/privateNameComputedPropertyName1.ts @@ -78,9 +76,7 @@ es2panda/test/TypeScript/tests/cases/conformance/es6/unicodeExtendedEscapes/unic es2panda/test/TypeScript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInRegularExpressions19_ES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck38.ts es2panda/test/TypeScript/tests/cases/conformance/expressions/elementAccess/letIdentifierInElementAccess01.ts -es2panda/test/TypeScript/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts es2panda/test/TypeScript/tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts -es2panda/test/TypeScript/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThis.ts es2panda/test/TypeScript/tests/cases/conformance/functions/functionWithUseStrictAndSimpleParameterList.ts es2panda/test/TypeScript/tests/cases/conformance/interfaces/interfaceDeclarations/asiPreventsParsingAsInterface01.ts es2panda/test/TypeScript/tests/cases/conformance/interfaces/interfaceDeclarations/asiPreventsParsingAsInterface03.ts -- Gitee From 1a0ba71649851e7b25e0f9f33e11849fc5934a86 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Mon, 17 Oct 2022 20:56:28 +0800 Subject: [PATCH 30/59] Support class without name implements interface Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5W6YI Test: parser tests, compiler tests, test262 Signed-off-by: xucheng46 Change-Id: Ia0f1c3bbc9c13878d13c63aa4bbea68193b2337c --- es2panda/parser/parserImpl.cpp | 3 +- .../ts/test-class-definiton21-expected.txt | 321 ++++++++++++++++++ .../test/parser/ts/test-class-definiton21.ts | 18 + es2panda/test/test_tsc_ignore_list.txt | 1 - 4 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 es2panda/test/parser/ts/test-class-definiton21-expected.txt create mode 100644 es2panda/test/parser/ts/test-class-definiton21.ts diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 905f1a5ed1..3094b02cc5 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2703,7 +2703,8 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i auto classCtx = binder::LexicalScope(Binder()); - if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { + if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && (Extension() != ScriptExtension::TS || + lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS)) { identNode = SetIdentNodeInClassDefinition(); } else if (isDeclaration && idRequired) { ThrowSyntaxError("Unexpected token, expected an identifier."); diff --git a/es2panda/test/parser/ts/test-class-definiton21-expected.txt b/es2panda/test/parser/ts/test-class-definiton21-expected.txt new file mode 100644 index 0000000000..0b95295e35 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton21-expected.txt @@ -0,0 +1,321 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "body": [], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "init": { + "type": "ClassExpression", + "definition": { + "id": null, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 26 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 26 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "body": [], + "indexSignatures": [], + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 29 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-class-definiton21.ts b/es2panda/test/parser/ts/test-class-definiton21.ts new file mode 100644 index 0000000000..f4c2ca7007 --- /dev/null +++ b/es2panda/test/parser/ts/test-class-definiton21.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +class A{} +var a = class implements A{} diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index 7212fc2461..14145dbad7 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -15,7 +15,6 @@ es2panda/test/TypeScript/tests/cases/compiler/exportRedeclarationTypeAliases.ts es2panda/test/TypeScript/tests/cases/compiler/fileWithNextLine2.ts es2panda/test/TypeScript/tests/cases/compiler/genericRecursiveImplicitConstructorErrors2.ts es2panda/test/TypeScript/tests/cases/compiler/globalIsContextualKeyword.ts -es2panda/test/TypeScript/tests/cases/compiler/implementsInClassExpression.ts es2panda/test/TypeScript/tests/cases/compiler/inferenceErasedSignatures.ts es2panda/test/TypeScript/tests/cases/compiler/isLiteral1.ts es2panda/test/TypeScript/tests/cases/compiler/noCircularDefinitionOnExportOfPrivateInMergedNamespace.ts -- Gitee From 2ad24cd9298fa12d4c4e784bbd11a909b2f1127f Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Sat, 29 Oct 2022 10:51:18 +0000 Subject: [PATCH 31/59] Fix incorrect error thrown of reserved word in class Issue:I5YEKP Signed-off-by: ctw-ian Change-Id: Ice2fecc1e9d30b08963c3dbec0bcba4cb5d8576d --- es2panda/parser/parserImpl.cpp | 4 +- .../js/class-declaration-is-expected.txt | 139 ++++++++++++++++++ .../test/parser/js/class-declaration-is.js | 1 + 3 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 es2panda/test/parser/js/class-declaration-is-expected.txt create mode 100644 es2panda/test/parser/js/class-declaration-is.js diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 905f1a5ed1..f4f8f17741 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2672,9 +2672,7 @@ bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition() { lexer::TokenType keywType = lexer_->GetToken().KeywordType(); - if (keywType >= lexer::TokenType::KEYW_STATIC) { - ThrowSyntaxError("Unexpected reserved word"); - } + CheckStrictReservedWord(); if (keywType == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) { ThrowSyntaxError("Unexpected reserved word"); diff --git a/es2panda/test/parser/js/class-declaration-is-expected.txt b/es2panda/test/parser/js/class-declaration-is-expected.txt new file mode 100644 index 0000000000..f83f21df96 --- /dev/null +++ b/es2panda/test/parser/js/class-declaration-is-expected.txt @@ -0,0 +1,139 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "is", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 9 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + "body": [], + "indexSignatures": [], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 12 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 12 + } + } +} diff --git a/es2panda/test/parser/js/class-declaration-is.js b/es2panda/test/parser/js/class-declaration-is.js new file mode 100644 index 0000000000..2e8c0c369b --- /dev/null +++ b/es2panda/test/parser/js/class-declaration-is.js @@ -0,0 +1 @@ +class is {} \ No newline at end of file -- Gitee From 586431c2288ca886524174e3aa158ba368485963 Mon Sep 17 00:00:00 2001 From: lordwithcc Date: Fri, 28 Oct 2022 14:15:55 +0800 Subject: [PATCH 32/59] Adapts to ts2abc for ark_standalone_build Signed-off-by: lordwithcc --- ts2panda/BUILD.gn | 18 +++--- ts2panda/ts2abc/BUILD.gn | 118 +++++++++++++++++++-------------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index c5f498c329..89de1457b4 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -259,13 +259,15 @@ ohos_copy("copy_ts2abc_tests") { module_install_name = "" } -group("ts2abc_unittests") { - if (host_os == "linux") { - testonly = true - deps = [ - "tests:ts2abc_ts_instruction_type_test(${toolchain_linux})", - "tests:ts2abc_ts_type_system_test(${toolchain_linux})", - "tests:ts2abc_ts_ut_test(${toolchain_linux})", - ] +if (!ark_standalone_build) { + group("ts2abc_unittests") { + if (host_os == "linux") { + testonly = true + deps = [ + "tests:ts2abc_ts_instruction_type_test(${toolchain_linux})", + "tests:ts2abc_ts_type_system_test(${toolchain_linux})", + "tests:ts2abc_ts_ut_test(${toolchain_linux})", + ] + } } } diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 19f7bc1a7b..eb7339ccb9 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -19,7 +19,7 @@ config("ts2abc_config") { visibility = [ ":*" ] include_dirs = [ ".", - "$jsoncpp_root/include", + "//third_party/jsoncpp/include", "$ark_root/libpandabase", ] @@ -58,79 +58,77 @@ source_set("jsoncpp_set_static") { public_configs = [ "$jsoncpp_root:jsoncpp_config" ] public_configs += [ ":flag_config" ] include_dirs = [ - "$jsoncpp_root/include", - "$jsoncpp_root/include/json/", + "//third_party/jsoncpp/include", + "//third_party/jsoncpp/include/json/", ] } -if (!ark_standalone_build) { - ohos_static_library("jsoncpp_static") { - deps = [ ":jsoncpp_set_static" ] - use_exceptions = true - part_name = "ets_frontend" - subsystem_name = "arkcompiler" - } +ohos_static_library("jsoncpp_static") { + deps = [ ":jsoncpp_set_static" ] + use_exceptions = true + part_name = "ets_frontend" + subsystem_name = "arkcompiler" +} - ohos_executable("ts2abc") { - sources = [ - "main.cpp", - "ts2abc.cpp", - ] +ohos_executable("ts2abc") { + sources = [ + "main.cpp", + "ts2abc.cpp", + ] - configs = [ ":ts2abc_config" ] + configs = [ ":ts2abc_config" ] - cflags = [ - "-Wno-c++20-designator", - "-Wno-c99-extensions", - "-Wno-unknown-warning-option", - ] + cflags = [ + "-Wno-c++20-designator", + "-Wno-c99-extensions", + "-Wno-unknown-warning-option", + ] - deps = [ - "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_static", - sdk_libc_secshared_dep, - ] + deps = [ + "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_static", + sdk_libc_secshared_dep, + ] - if (is_linux || is_mingw || is_mac) { + if (is_linux || is_mingw || is_mac) { + deps += [ + "$ark_root/assembler:libarkassembler_frontend_static", + "$ark_root/libpandabase:libarkbase_frontend_static", + "$ark_root/libpandafile:libarkfile_frontend_static", + "$ark_root/libziparchive:libarkziparchive_frontend_static", + "$ark_third_party_root/jsoncpp:jsoncpp_static", + ] + if (enable_bytecode_optimizer) { deps += [ - "$ark_root/assembler:libarkassembler_frontend_static", - "$ark_root/libpandabase:libarkbase_frontend_static", - "$ark_root/libpandafile:libarkfile_frontend_static", - "$ark_root/libziparchive:libarkziparchive_frontend_static", - "//third_party/jsoncpp:jsoncpp_static", + "$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static", + "$ark_root/compiler:libarkcompiler_frontend_static", ] - if (enable_bytecode_optimizer) { - deps += [ - "$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static", - "$ark_root/compiler:libarkcompiler_frontend_static", - ] - } - } else { + } + } else { + deps += [ + "$ark_root/assembler:libarkassembler", + "$ark_root/libpandabase:libarkbase", + "$ark_root/libpandafile:libarkfile", + "$ark_root/libziparchive:libarkziparchive", + "$jsoncpp_root:jsoncpp", + ] + if (enable_bytecode_optimizer) { deps += [ - "$ark_root/assembler:libarkassembler", - "$ark_root/libpandabase:libarkbase", - "$ark_root/libpandafile:libarkfile", - "$ark_root/libziparchive:libarkziparchive", - "$jsoncpp_root:jsoncpp", + "$ark_root/bytecode_optimizer:libarkbytecodeopt", + "$ark_root/compiler:libarkcompiler", ] - if (enable_bytecode_optimizer) { - deps += [ - "$ark_root/bytecode_optimizer:libarkbytecodeopt", - "$ark_root/compiler:libarkcompiler", - ] - } } + } - if (is_linux) { - if (build_public_version) { - ldflags = [ "-static-libstdc++" ] - } else { - libs = [ libcpp_static_lib ] - } + if (is_linux) { + if (build_public_version) { + ldflags = [ "-static-libstdc++" ] + } else { + libs = [ libcpp_static_lib ] } - - output_name = "js2abc" - install_enable = false - part_name = "ets_frontend" - subsystem_name = "arkcompiler" } + + output_name = "js2abc" + install_enable = false + part_name = "ets_frontend" + subsystem_name = "arkcompiler" } -- Gitee From abee7dc80ecffd69867a1df6fba63c109122908b Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Tue, 18 Oct 2022 20:48:02 +0800 Subject: [PATCH 33/59] Enable conditional expression in parentheses Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5WF1Q Test: parser tests, compiler tests, test262 Signed-off-by: xucheng46 Change-Id: I7f3ba903345368d6632a62ac4f980d80aa842365 --- es2panda/lexer/token/token.cpp | 7 +- es2panda/lexer/token/token.h | 2 +- es2panda/parser/expressionParser.cpp | 9 +- .../ts/test-arrow-function3-expected.txt | 292 ++++++++++++++++++ .../test/parser/ts/test-arrow-function3.ts | 19 ++ es2panda/test/test_tsc_ignore_list.txt | 3 - 6 files changed, 322 insertions(+), 10 deletions(-) create mode 100644 es2panda/test/parser/ts/test-arrow-function3-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function3.ts diff --git a/es2panda/lexer/token/token.cpp b/es2panda/lexer/token/token.cpp index 61847be143..9bf5799002 100644 --- a/es2panda/lexer/token/token.cpp +++ b/es2panda/lexer/token/token.cpp @@ -15,6 +15,8 @@ #include "token.h" +#include "letters.h" + namespace panda::es2panda::lexer { bool Token::IsAccessability() const @@ -132,9 +134,10 @@ bool Token::IsPunctuatorToken(TokenType type) return (type >= TokenType::PUNCTUATOR_NULLISH_COALESCING && type <= TokenType::PUNCTUATOR_ARROW); } -bool Token::IsTsParamToken(TokenType type) +bool Token::IsTsParamToken(TokenType type, char32_t nextChar) { - return (type == TokenType::PUNCTUATOR_COLON || type == TokenType::PUNCTUATOR_QUESTION_MARK); + return (type == TokenType::PUNCTUATOR_COLON || (type == TokenType::PUNCTUATOR_QUESTION_MARK && + (nextChar == LEX_CHAR_COMMA || nextChar == LEX_CHAR_COLON || nextChar == LEX_CHAR_RIGHT_PAREN))); } const char *TokenToString(TokenType type) diff --git a/es2panda/lexer/token/token.h b/es2panda/lexer/token/token.h index 26edb60d38..e782439617 100644 --- a/es2panda/lexer/token/token.h +++ b/es2panda/lexer/token/token.h @@ -122,7 +122,7 @@ public: static bool IsBinaryLvalueToken(TokenType type); static bool IsUpdateToken(TokenType type); static bool IsPunctuatorToken(TokenType type); - static bool IsTsParamToken(TokenType type); + static bool IsTsParamToken(TokenType type, char32_t nextChar); private: friend class KeywordsUtil; diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index cb6d065fdf..d3aa38c134 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -256,7 +256,7 @@ ir::Expression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags) } if (Extension() == ScriptExtension::TS && (flags & ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN) && - lexer::Token::IsTsParamToken(lexer_->GetToken().Type())) { + lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) { context_.Status() |= ParserStatus::FUNCTION_PARAM; ParsePotentialTsFunctionParameter(ExpressionParseFlags::NO_OPTS, arrayExpressionNode); } @@ -551,7 +551,8 @@ ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterLi restElement->SetGrouped(); restElement->SetStart(start); - if (Extension() == ScriptExtension::TS && lexer::Token::IsTsParamToken(lexer_->GetToken().Type())) { + if (Extension() == ScriptExtension::TS && + lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) { ParsePotentialTsFunctionParameter(ExpressionParseFlags::IN_REST, restElement); } @@ -976,7 +977,7 @@ ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags) lexer_->NextToken(); if (Extension() == ScriptExtension::TS && (flags & ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN) && - lexer::Token::IsTsParamToken(lexer_->GetToken().Type())) { + lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) { context_.Status() |= ParserStatus::FUNCTION_PARAM; ParsePotentialTsFunctionParameter(ExpressionParseFlags::NO_OPTS, identNode); } @@ -2152,7 +2153,7 @@ ir::ObjectExpression *ParserImpl::ParseObjectExpression(ExpressionParseFlags fla } if (Extension() == ScriptExtension::TS && (flags & ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN) && - lexer::Token::IsTsParamToken(lexer_->GetToken().Type())) { + lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) { context_.Status() |= ParserStatus::FUNCTION_PARAM; ParsePotentialTsFunctionParameter(ExpressionParseFlags::NO_OPTS, objectExpression); } diff --git a/es2panda/test/parser/ts/test-arrow-function3-expected.txt b/es2panda/test/parser/ts/test-arrow-function3-expected.txt new file mode 100644 index 0000000000..6acf39acce --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function3-expected.txt @@ -0,0 +1,292 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "TSBooleanKeyword", + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 6 + } + } + }, + "init": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "init": { + "type": "ConditionalExpression", + "test": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 11 + } + } + }, + "consequent": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "a", + "optional": true, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 13 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 19 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 19 + } + } +} diff --git a/es2panda/test/parser/ts/test-arrow-function3.ts b/es2panda/test/parser/ts/test-arrow-function3.ts new file mode 100644 index 0000000000..571ebe40a1 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function3.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 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. + */ + + +var a : boolean = true; +var b = (a ? 1 : 2) +var c = (a?) => {} \ No newline at end of file diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index 84265f688b..8e94cefa38 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -6,7 +6,6 @@ es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInterfaceMembers es2panda/test/TypeScript/tests/cases/compiler/computedPropertiesTransformedInOtherwiseNonTSClasses.ts es2panda/test/TypeScript/tests/cases/compiler/constructorOverloads5.ts es2panda/test/TypeScript/tests/cases/compiler/continueTarget3.ts -es2panda/test/TypeScript/tests/cases/compiler/controlFlowCaching.ts es2panda/test/TypeScript/tests/cases/compiler/declarationEmitDestructuringOptionalBindingParametersInOverloads.ts es2panda/test/TypeScript/tests/cases/compiler/discriminantsAndPrimitives.ts es2panda/test/TypeScript/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts @@ -86,7 +85,6 @@ es2panda/test/TypeScript/tests/cases/conformance/interfaces/interfaceDeclaration es2panda/test/TypeScript/tests/cases/conformance/interfaces/interfaceDeclarations/asiPreventsParsingAsInterface03.ts es2panda/test/TypeScript/tests/cases/conformance/interfaces/interfaceDeclarations/asiPreventsParsingAsInterface04.ts es2panda/test/TypeScript/tests/cases/conformance/internalModules/moduleDeclarations/asiPreventsParsingAsNamespace04.ts -es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression6.ts es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/RegressionTests/parser579071.ts es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget3.ts es2panda/test/TypeScript/tests/cases/conformance/parser/ecmascript5/parserUnicodeWhitespaceCharacter1.ts @@ -94,7 +92,6 @@ es2panda/test/TypeScript/tests/cases/conformance/scanner/ecmascript3/scannerES3N es2panda/test/TypeScript/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts es2panda/test/TypeScript/tests/cases/conformance/types/members/objectTypeWithStringNamedNumericProperty.ts es2panda/test/TypeScript/tests/cases/conformance/types/specifyingTypes/typeQueries/typeQueryWithReservedWords.ts -es2panda/test/TypeScript/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts es2panda/test/TypeScript/tests/cases/conformance/types/tuple/named/namedTupleMembers.ts es2panda/test/TypeScript/tests/cases/conformance/types/typeParameters/typeArgumentLists/constraintSatisfactionWithEmptyObject.ts es2panda/test/TypeScript/tests/cases/conformance/types/uniqueSymbol/uniqueSymbols.ts -- Gitee From 61cc5cc773d78b2621bab9be25dcad9fa478813b Mon Sep 17 00:00:00 2001 From: zhuoli Date: Wed, 2 Nov 2022 09:50:21 +0800 Subject: [PATCH 34/59] Add output dir for prebuilt gn targets to avoid having multiple rules generating the same target Signed-off-by: zhuoli Change-Id: I43b6bb32515cffa750a4fab9f59a187f43442da1 --- legacy_bin/BUILD.gn | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/legacy_bin/BUILD.gn b/legacy_bin/BUILD.gn index c8e5856335..542b8377e6 100644 --- a/legacy_bin/BUILD.gn +++ b/legacy_bin/BUILD.gn @@ -16,72 +16,84 @@ import("//build/ohos.gni") # for js-loader ohos_prebuilt_executable("js_js2abc_api8_linux") { source = "./api8/bin/linux/js2abc" + output = "js_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_executable("js_js2abc_api8_win") { source = "./api8/bin/win/js2abc.exe" + output = "js_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_executable("js_js2abc_api8_mac") { source = "./api8/bin/mac/js2abc" + output = "js_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_ts2abc_api8_linux") { source = "./api8/src/index.js" + output = "js_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_ts2abc_api8_win") { source = "./api8/src/index.js" + output = "js_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_ts2abc_api8_mac") { source = "./api8/src/index.js" + output = "js_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package_api8_linux") { source = "./api8/package.json" + output = "js_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package_api8_win") { source = "./api8/package.json" + output = "js_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package_api8_mac") { source = "./api8/package.json" + output = "js_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package-lock_api8_linux") { source = "./api8/package-lock.json" + output = "js_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package-lock_api8_win") { source = "./api8/package-lock.json" + output = "js_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("js_package-lock_api8_mac") { source = "./api8/package-lock.json" + output = "js_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } @@ -89,72 +101,84 @@ ohos_prebuilt_etc("js_package-lock_api8_mac") { # for ets-loader ohos_prebuilt_executable("ets_js2abc_api8_linux") { source = "./api8/bin/linux/js2abc" + output = "ets_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_executable("ets_js2abc_api8_win") { source = "./api8/bin/win/js2abc.exe" + output = "ets_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_executable("ets_js2abc_api8_mac") { source = "./api8/bin/mac/js2abc" + output = "ets_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_ts2abc_api8_linux") { source = "./api8/src/index.js" + output = "ets_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_ts2abc_api8_win") { source = "./api8/src/index.js" + output = "ets_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_ts2abc_api8_mac") { source = "./api8/src/index.js" + output = "ets_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package_api8_linux") { source = "./api8/package.json" + output = "ets_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package_api8_win") { source = "./api8/package.json" + output = "ets_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package_api8_mac") { source = "./api8/package.json" + output = "ets_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package-lock_api8_linux") { source = "./api8/package-lock.json" + output = "ets_linux/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package-lock_api8_win") { source = "./api8/package-lock.json" + output = "ets_win/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } ohos_prebuilt_etc("ets_package-lock_api8_mac") { source = "./api8/package-lock.json" + output = "ets_mac/${source}" part_name = "ets_frontend" subsystem_name = "arkcompiler" } -- Gitee From ef683da8da7b0cf944e7cd348c4feb1f668eb1ce Mon Sep 17 00:00:00 2001 From: zengyuan Date: Mon, 17 Oct 2022 16:37:25 +0800 Subject: [PATCH 35/59] Fix bug of Es2abc Description: Fix three error cases: Missing initializer in destructuring declaration Unexpect modifier on private identifier A required element cannot follow an optional element Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5WP6Z Signed-off-by: zengyuan Change-Id: I946ef94acecd05ebc62c6591de4ae91e85590959 --- es2panda/parser/parserImpl.cpp | 8 +- es2panda/parser/statementParser.cpp | 3 +- .../test-destructure-declaration-expected.txt | 231 ++++++++++++ .../parser/ts/test-destructure-declaration.ts | 18 + .../ts/test-private-identifier-expected.txt | 338 ++++++++++++++++++ .../test/parser/ts/test-private-identifier.ts | 21 ++ .../parser/ts/test-tuple-type11-expected.txt | 1 + es2panda/test/parser/ts/test-tuple-type11.ts | 18 + .../parser/ts/test-tuple-type6-expected.txt | 209 +++++++++++ es2panda/test/parser/ts/test-tuple-type6.ts | 17 + es2panda/test/test_tsc_ignore_list.txt | 3 - 11 files changed, 861 insertions(+), 6 deletions(-) create mode 100644 es2panda/test/parser/ts/test-destructure-declaration-expected.txt create mode 100644 es2panda/test/parser/ts/test-destructure-declaration.ts create mode 100644 es2panda/test/parser/ts/test-private-identifier-expected.txt create mode 100644 es2panda/test/parser/ts/test-private-identifier.ts create mode 100644 es2panda/test/parser/ts/test-tuple-type11-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type11.ts create mode 100644 es2panda/test/parser/ts/test-tuple-type6-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type6.ts diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 1fce8241a5..c1af0bba70 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -831,7 +831,7 @@ ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *see lexer_->NextToken(); // eat '?' isOptional = true; *seenOptional = true; - } else if (*seenOptional) { + } else if (*seenOptional && !isRestType) { ThrowSyntaxError("A required element cannot follow an optional element"); } @@ -864,6 +864,10 @@ ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *see element = AllocNode(std::move(element)); element->SetRange({elementStartPos, lexer_->GetToken().End()}); lexer_->NextToken(); // eat '?' + isOptional = true; + *seenOptional = true; + } else if (*seenOptional && !isRestType) { + ThrowSyntaxError("A required element cannot follow an optional element"); } } return element; @@ -2400,7 +2404,7 @@ void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc) return; } - if (desc->modifiers != ir::ModifierFlags::NONE) { + if (desc->modifiers & ~ir::ModifierFlags::READONLY) { ThrowSyntaxError("Unexpected modifier on private identifier"); } diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 6c8250593d..aea10c255c 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -1949,7 +1949,8 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags ThrowSyntaxError("Missing initializer in const declaration"); } - if (!(flags & VariableParsingFlags::IN_FOR) && (init->IsArrayPattern() || init->IsObjectPattern())) { + if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) && + (init->IsArrayPattern() || init->IsObjectPattern())) { ThrowSyntaxError("Missing initializer in destructuring declaration"); } diff --git a/es2panda/test/parser/ts/test-destructure-declaration-expected.txt b/es2panda/test/parser/ts/test-destructure-declaration-expected.txt new file mode 100644 index 0000000000..f3f5547d00 --- /dev/null +++ b/es2panda/test/parser/ts/test-destructure-declaration-expected.txt @@ -0,0 +1,231 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "ArrayPattern", + "elements": [ + { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 19 + } + } + } + ], + "kind": "var", + "declare": true, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "ObjectPattern", + "properties": [ + { + "type": "Property", + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "value": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + { + "type": "Property", + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 18 + } + } + }, + "value": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 18 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + } + ], + "kind": "var", + "declare": true, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 20 + } + } +} diff --git a/es2panda/test/parser/ts/test-destructure-declaration.ts b/es2panda/test/parser/ts/test-destructure-declaration.ts new file mode 100644 index 0000000000..f913fd152e --- /dev/null +++ b/es2panda/test/parser/ts/test-destructure-declaration.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +declare var [a, b]; +declare var {c, d}; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-private-identifier-expected.txt b/es2panda/test/parser/ts/test-private-identifier-expected.txt new file mode 100644 index 0000000000..7d35e2485b --- /dev/null +++ b/es2panda/test/parser/ts/test-private-identifier-expected.txt @@ -0,0 +1,338 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "TSPrivateIdentifier", + "key": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 7 + } + } + }, + "value": { + "type": "StringLiteral", + "value": "b", + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 7 + } + } + }, + "value": { + "type": "StringLiteral", + "value": "b", + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "value": { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "static": false, + "readonly": true, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "TSPrivateIdentifier", + "key": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "value": { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "value": { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "static": false, + "readonly": true, + "declare": false, + "optional": false, + "computed": false, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 22 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } +} diff --git a/es2panda/test/parser/ts/test-private-identifier.ts b/es2panda/test/parser/ts/test-private-identifier.ts new file mode 100644 index 0000000000..db2f85b9a4 --- /dev/null +++ b/es2panda/test/parser/ts/test-private-identifier.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +class A { + #b = 'b'; + readonly a = 'a'; + readonly #c = 'c'; +} \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-tuple-type11-expected.txt b/es2panda/test/parser/ts/test-tuple-type11-expected.txt new file mode 100644 index 0000000000..35f4840365 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type11-expected.txt @@ -0,0 +1 @@ +SyntaxError: A required element cannot follow an optional element [test-tuple-type11.ts:18:50] diff --git a/es2panda/test/parser/ts/test-tuple-type11.ts b/es2panda/test/parser/ts/test-tuple-type11.ts new file mode 100644 index 0000000000..27a1d3676a --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type11.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +type WithOptAndRest1 = [number, number?, ...string[]]; +type WithOptAndRest2 = [number, number?, string[]]; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-tuple-type6-expected.txt b/es2panda/test/parser/ts/test-tuple-type6-expected.txt new file mode 100644 index 0000000000..02a117c4e6 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type6-expected.txt @@ -0,0 +1,209 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "WithOptAndRest", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 6 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "typeAnnotation": { + "type": "TSTupleType", + "elementTypes": [ + { + "type": "TSNamedTupleMember", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 31 + }, + "end": { + "line": 17, + "column": 37 + } + } + }, + "label": { + "type": "Identifier", + "name": "first", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 37 + } + } + }, + { + "type": "TSNamedTupleMember", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 48 + }, + "end": { + "line": 17, + "column": 54 + } + } + }, + "label": { + "type": "Identifier", + "name": "second", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 39 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + "optional": true, + "loc": { + "start": { + "line": 17, + "column": 39 + }, + "end": { + "line": 17, + "column": 54 + } + } + }, + { + "type": "TSNamedTupleMember", + "elementType": { + "type": "TSArrayType", + "elementType": { + "type": "TSStringKeyword", + "loc": { + "start": { + "line": 17, + "column": 65 + }, + "end": { + "line": 17, + "column": 71 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 65 + }, + "end": { + "line": 17, + "column": 73 + } + } + }, + "label": { + "type": "Identifier", + "name": "rest", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 59 + }, + "end": { + "line": 17, + "column": 63 + } + } + }, + "rest": true, + "loc": { + "start": { + "line": 17, + "column": 56 + }, + "end": { + "line": 17, + "column": 73 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 74 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 75 + } + } + }, + { + "type": "EmptyStatement", + "loc": { + "start": { + "line": 17, + "column": 74 + }, + "end": { + "line": 17, + "column": 75 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 75 + } + } +} diff --git a/es2panda/test/parser/ts/test-tuple-type6.ts b/es2panda/test/parser/ts/test-tuple-type6.ts new file mode 100644 index 0000000000..a7883e92fc --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type6.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +type WithOptAndRest = [first: number, second?: number, ...rest: string[]]; \ No newline at end of file diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index 1bebc33d4a..4aff71e039 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -36,7 +36,6 @@ es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringFo es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/withStatementInternalComments.ts es2panda/test/TypeScript/tests/cases/conformance/async/es2017/asyncAwait_es2017.ts -es2panda/test/TypeScript/tests/cases/conformance/classes/members/privateNames/privateNameComputedPropertyName1.ts es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments03_ES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments04_ES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments05_ES6.ts @@ -51,7 +50,6 @@ es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunc es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments15_ES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments16_ES6.ts es2panda/test/TypeScript/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionWhenUsingArguments17_ES6.ts -es2panda/test/TypeScript/tests/cases/conformance/es6/destructuring/declarationInAmbientContext.ts es2panda/test/TypeScript/tests/cases/conformance/es6/for-ofStatements/for-of53.ts es2panda/test/TypeScript/tests/cases/conformance/es6/for-ofStatements/for-of56.ts es2panda/test/TypeScript/tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts @@ -87,7 +85,6 @@ es2panda/test/TypeScript/tests/cases/conformance/scanner/ecmascript3/scannerES3N es2panda/test/TypeScript/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts es2panda/test/TypeScript/tests/cases/conformance/types/members/objectTypeWithStringNamedNumericProperty.ts es2panda/test/TypeScript/tests/cases/conformance/types/specifyingTypes/typeQueries/typeQueryWithReservedWords.ts -es2panda/test/TypeScript/tests/cases/conformance/types/tuple/named/namedTupleMembers.ts es2panda/test/TypeScript/tests/cases/conformance/types/typeParameters/typeArgumentLists/constraintSatisfactionWithEmptyObject.ts es2panda/test/TypeScript/tests/cases/conformance/types/uniqueSymbol/uniqueSymbols.ts es2panda/test/TypeScript/tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarations.ts -- Gitee From 1cb5e4059421f73b794ee045f47124275196e702 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Thu, 27 Oct 2022 03:45:46 +0000 Subject: [PATCH 36/59] Enable parser import/export type Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5XZSK Test: parser tests, compiler tests, test262 Signed-off-by: xucheng46 Change-Id: I5cee1bc9c78376724d6b4a5fb633af330cc3217c --- es2panda/binder/binder.cpp | 2 +- es2panda/ir/module/exportNamedDeclaration.cpp | 3 +- es2panda/ir/module/exportNamedDeclaration.h | 14 +- es2panda/ir/module/importDeclaration.cpp | 5 +- es2panda/ir/module/importDeclaration.h | 13 +- es2panda/parser/parserImpl.h | 2 +- es2panda/parser/statementParser.cpp | 41 ++- .../parser/ts/test-export-type-expected.txt | 273 ++++++++++++++++++ es2panda/test/parser/ts/test-export-type.ts | 20 ++ .../parser/ts/test-import-type-expected.txt | 261 +++++++++++++++++ es2panda/test/parser/ts/test-import-type.ts | 20 ++ 11 files changed, 640 insertions(+), 14 deletions(-) create mode 100644 es2panda/test/parser/ts/test-export-type-expected.txt create mode 100644 es2panda/test/parser/ts/test-export-type.ts create mode 100644 es2panda/test/parser/ts/test-import-type-expected.txt create mode 100644 es2panda/test/parser/ts/test-import-type.ts diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 6ad17db5ea..3ce0f603f9 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -120,7 +120,7 @@ void Binder::IdentifierAnalysis(ResolveBindingFlags flags) void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl) { - if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr) { + if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr || exportDecl->IsType()) { return; } diff --git a/es2panda/ir/module/exportNamedDeclaration.cpp b/es2panda/ir/module/exportNamedDeclaration.cpp index b8a0f08ce9..b379ed7a27 100644 --- a/es2panda/ir/module/exportNamedDeclaration.cpp +++ b/es2panda/ir/module/exportNamedDeclaration.cpp @@ -42,7 +42,8 @@ void ExportNamedDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ExportNamedDeclaration"}, {"declaration", AstDumper::Nullable(decl_)}, {"source", AstDumper::Nullable(source_)}, - {"specifiers", specifiers_}}); + {"specifiers", specifiers_}, + {"isType", AstDumper::Optional(IsType())}}); } void ExportNamedDeclaration::Compile(compiler::PandaGen *pg) const diff --git a/es2panda/ir/module/exportNamedDeclaration.h b/es2panda/ir/module/exportNamedDeclaration.h index d863428fe3..3185da787e 100644 --- a/es2panda/ir/module/exportNamedDeclaration.h +++ b/es2panda/ir/module/exportNamedDeclaration.h @@ -34,11 +34,12 @@ class ExportSpecifier; class ExportNamedDeclaration : public Statement { public: - explicit ExportNamedDeclaration(StringLiteral *source, ArenaVector &&specifiers) + explicit ExportNamedDeclaration(StringLiteral *source, ArenaVector &&specifiers, bool isType) : Statement(AstNodeType::EXPORT_NAMED_DECLARATION), source_(source), decl_(nullptr), - specifiers_(std::move(specifiers)) + specifiers_(std::move(specifiers)), + isType_(isType) { } @@ -46,7 +47,8 @@ public: : Statement(AstNodeType::EXPORT_NAMED_DECLARATION), source_(nullptr), decl_(decl), - specifiers_(std::move(specifiers)) + specifiers_(std::move(specifiers)), + isType_(false) { } @@ -70,6 +72,11 @@ public: return specifiers_; } + bool IsType() const + { + return isType_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; @@ -80,6 +87,7 @@ private: StringLiteral *source_; Statement *decl_; ArenaVector specifiers_; + bool isType_; }; } // namespace panda::es2panda::ir diff --git a/es2panda/ir/module/importDeclaration.cpp b/es2panda/ir/module/importDeclaration.cpp index b6f1165012..8c6a8afda7 100644 --- a/es2panda/ir/module/importDeclaration.cpp +++ b/es2panda/ir/module/importDeclaration.cpp @@ -31,7 +31,10 @@ void ImportDeclaration::Iterate(const NodeTraverser &cb) const void ImportDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ImportDeclaration"}, {"source", source_}, {"specifiers", specifiers_}}); + dumper->Add({{"type", "ImportDeclaration"}, + {"source", source_}, + {"specifiers", specifiers_}, + {"isType", AstDumper::Optional(IsType())}}); } void ImportDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} diff --git a/es2panda/ir/module/importDeclaration.h b/es2panda/ir/module/importDeclaration.h index 271f5f1c8f..a51e4fa5d5 100644 --- a/es2panda/ir/module/importDeclaration.h +++ b/es2panda/ir/module/importDeclaration.h @@ -34,8 +34,11 @@ class StringLiteral; class ImportDeclaration : public Statement { public: - explicit ImportDeclaration(StringLiteral *source, ArenaVector &&specifiers) - : Statement(AstNodeType::IMPORT_DECLARATION), source_(source), specifiers_(std::move(specifiers)) + explicit ImportDeclaration(StringLiteral *source, ArenaVector &&specifiers, bool isType) + : Statement(AstNodeType::IMPORT_DECLARATION), + source_(source), + specifiers_(std::move(specifiers)), + isType_(isType) { } @@ -49,6 +52,11 @@ public: return specifiers_; } + bool IsType() const + { + return isType_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; @@ -58,6 +66,7 @@ public: private: StringLiteral *source_; ArenaVector specifiers_; + bool isType_; }; } // namespace panda::es2panda::ir diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index fc1663e5e9..2c45441d6e 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -409,7 +409,7 @@ private: ArenaVector decorators, bool isExportEquals = false); ir::ExportAllDeclaration *ParseExportAllDeclaration(const lexer::SourcePosition &startLoc); - ir::ExportNamedDeclaration *ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc); + ir::ExportNamedDeclaration *ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc, bool isType); ir::ExportNamedDeclaration *ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc, ArenaVector &&decorators); ir::Identifier *ParseNamedExport(const lexer::Token &exportedToken); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index aea10c255c..33ae6aa2b0 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -2345,7 +2345,8 @@ ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::Sou return exportDeclaration; } -ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc) +ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc, + bool isType) { lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character @@ -2396,9 +2397,11 @@ ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer:: } // record ExportEntry - AddExportNamedEntryItem(specifiers, source); + if (!isType) { + AddExportNamedEntryItem(specifiers, source); + } - auto *exportDeclaration = AllocNode(source, std::move(specifiers)); + auto *exportDeclaration = AllocNode(source, std::move(specifiers), isType); exportDeclaration->SetRange({startLoc, endPos}); ConsumeSemicolon(exportDeclaration); @@ -2528,6 +2531,19 @@ ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags, lexer::SourcePosition startLoc = lexer_->GetToken().Start(); lexer_->NextToken(); // eat `export` keyword + // won't set `isType` for type alias + bool isType = false; + if (Extension() == ScriptExtension::TS && + lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { + const auto savedPos = lexer_->Save(); + lexer_->NextToken(); // eat type + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + isType = true; + } else { + lexer_->Rewind(savedPos); + } + } + switch (lexer_->GetToken().Type()) { case lexer::TokenType::KEYW_DEFAULT: { // export default Id return ParseExportDefaultDeclaration(startLoc, std::move(decorators)); @@ -2536,7 +2552,7 @@ ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags, return ParseExportAllDeclaration(startLoc); } case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ... - return ParseExportNamedSpecifiers(startLoc); + return ParseExportNamedSpecifiers(startLoc, isType); } case lexer::TokenType::KEYW_IMPORT: { return ParseTsImportEqualsDeclaration(startLoc, true); @@ -2802,6 +2818,21 @@ ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags) lexer::SourcePosition startLoc = lexer_->GetToken().Start(); lexer_->NextToken(); // eat import + bool isType = false; + if (Extension() == ScriptExtension::TS && + lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { + const auto savedPos = lexer_->Save(); + lexer_->NextToken(); // eat type + if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && + lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { + isType = true; + } else { + lexer_->Rewind(savedPos); + } + } + ArenaVector specifiers(Allocator()->Adapter()); ir::StringLiteral *source = nullptr; @@ -2823,7 +2854,7 @@ ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags) } lexer::SourcePosition endLoc = source->End(); - auto *importDeclaration = AllocNode(source, std::move(specifiers)); + auto *importDeclaration = AllocNode(source, std::move(specifiers), isType); importDeclaration->SetRange({startLoc, endLoc}); ConsumeSemicolon(importDeclaration); diff --git a/es2panda/test/parser/ts/test-export-type-expected.txt b/es2panda/test/parser/ts/test-export-type-expected.txt new file mode 100644 index 0000000000..0feb64bb1b --- /dev/null +++ b/es2panda/test/parser/ts/test-export-type-expected.txt @@ -0,0 +1,273 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + { + "type": "EmptyStatement", + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 7 + } + } + }, + "typeAnnotation": { + "type": "TSStringKeyword", + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + { + "type": "EmptyStatement", + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "exported": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "isType": true, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 17 + } + } + }, + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": { + "type": "StringLiteral", + "value": "./C", + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 27 + } + } + }, + "specifiers": [ + { + "type": "ExportSpecifier", + "local": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "exported": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + } + ], + "isType": true, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 28 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-export-type.ts b/es2panda/test/parser/ts/test-export-type.ts new file mode 100644 index 0000000000..222885cb5a --- /dev/null +++ b/es2panda/test/parser/ts/test-export-type.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export type a = number; +type b = string; +export type {b}; +export type {c} from "./C"; diff --git a/es2panda/test/parser/ts/test-import-type-expected.txt b/es2panda/test/parser/ts/test-import-type-expected.txt new file mode 100644 index 0000000000..4429fe297a --- /dev/null +++ b/es2panda/test/parser/ts/test-import-type-expected.txt @@ -0,0 +1,261 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./A", + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "specifiers": [ + { + "type": "ImportSpecifier", + "local": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "imported": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 15 + } + } + } + ], + "isType": true, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./B", + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 14 + } + } + } + ], + "isType": true, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./C", + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "specifiers": [ + { + "type": "ImportNamespaceSpecifier", + "local": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + } + ], + "isType": true, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 31 + } + } + }, + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./D", + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "type", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 8 + }, + "end": { + "line": 20, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 8 + }, + "end": { + "line": 20, + "column": 12 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-import-type.ts b/es2panda/test/parser/ts/test-import-type.ts new file mode 100644 index 0000000000..6b5fbe4b80 --- /dev/null +++ b/es2panda/test/parser/ts/test-import-type.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 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 type {a} from "./A"; +import type b from "./B"; +import type * as c from "./C"; +import type from "./D"; -- Gitee From f649392b558d6d5f25139c5ba6099b2c3457f15f Mon Sep 17 00:00:00 2001 From: songqi Date: Thu, 22 Sep 2022 10:05:16 +0800 Subject: [PATCH 37/59] Enable enum emitting in es2abc Issue: I5WVR2 Test: test262, parser tests, compiler tests, tsc Signed-off-by: songqi Change-Id: Icbdba0f9d70aa80fc1398759e8ea81c8fd278fe3 --- es2panda/binder/binder.cpp | 19 +- es2panda/binder/binder.h | 6 +- es2panda/binder/declaration.h | 28 +- es2panda/binder/scope.cpp | 33 +- es2panda/binder/scope.h | 44 +- es2panda/binder/variable.cpp | 1 + es2panda/binder/variable.h | 59 ++ es2panda/binder/variableFlags.h | 8 +- es2panda/compiler/base/hoisting.cpp | 2 +- es2panda/compiler/core/function.cpp | 2 +- es2panda/ir/expressions/binaryExpression.h | 5 + es2panda/ir/expressions/memberExpression.h | 5 + es2panda/ir/ts/tsEnumDeclaration.cpp | 15 +- es2panda/ir/ts/tsEnumDeclaration.h | 22 +- es2panda/ir/ts/tsEnumMember.h | 6 + es2panda/parser/parserImpl.cpp | 53 +- es2panda/parser/parserImpl.h | 7 +- es2panda/parser/statementParser.cpp | 16 +- es2panda/parser/transformer/transformer.cpp | 701 ++++++++++++++++-- es2panda/parser/transformer/transformer.h | 61 +- .../enums/test-ts-enum-1-expected.txt | 14 + .../cases/conformance/enums/test-ts-enum-1.ts | 44 ++ .../enums/test-ts-enum-10-expected.txt | 1 + .../conformance/enums/test-ts-enum-10.ts | 21 + .../enums/test-ts-enum-11-expected.txt | 5 + .../conformance/enums/test-ts-enum-11.ts | 38 + .../enums/test-ts-enum-12-expected.txt | 7 + .../conformance/enums/test-ts-enum-12.ts | 31 + .../enums/test-ts-enum-13-expected.txt | 1 + .../conformance/enums/test-ts-enum-13.ts | 28 + .../enums/test-ts-enum-14-expected.txt | 1 + .../conformance/enums/test-ts-enum-14.ts | 26 + .../enums/test-ts-enum-15-expected.txt | 2 + .../conformance/enums/test-ts-enum-15.ts | 31 + .../enums/test-ts-enum-16-expected.txt | 9 + .../conformance/enums/test-ts-enum-16.ts | 49 ++ .../enums/test-ts-enum-17-expected.txt | 3 + .../conformance/enums/test-ts-enum-17.ts | 36 + .../enums/test-ts-enum-18-expected.txt | 1 + .../conformance/enums/test-ts-enum-18.ts | 31 + .../enums/test-ts-enum-19-expected.txt | 1 + .../conformance/enums/test-ts-enum-19.ts | 28 + .../enums/test-ts-enum-2-expected.txt | 11 + .../cases/conformance/enums/test-ts-enum-2.ts | 43 ++ .../enums/test-ts-enum-20-expected.txt | 6 + .../conformance/enums/test-ts-enum-20.ts | 37 + .../enums/test-ts-enum-21-expected.txt | 6 + .../conformance/enums/test-ts-enum-21.ts | 39 + .../enums/test-ts-enum-22-expected.txt | 2 + .../conformance/enums/test-ts-enum-22.ts | 27 + .../enums/test-ts-enum-23-expected.txt | 2 + .../conformance/enums/test-ts-enum-23.ts | 28 + .../enums/test-ts-enum-24-expected.txt | 2 + .../conformance/enums/test-ts-enum-24.ts | 32 + .../enums/test-ts-enum-25-expected.txt | 2 + .../conformance/enums/test-ts-enum-25.ts | 25 + .../enums/test-ts-enum-26-expected.txt | 3 + .../conformance/enums/test-ts-enum-26.ts | 47 ++ .../enums/test-ts-enum-27-expected.txt | 3 + .../conformance/enums/test-ts-enum-27.ts | 37 + .../enums/test-ts-enum-28-expected.txt | 2 + .../conformance/enums/test-ts-enum-28.ts | 30 + .../enums/test-ts-enum-29-expected.txt | 3 + .../conformance/enums/test-ts-enum-29.ts | 29 + .../enums/test-ts-enum-3-expected.txt | 2 + .../cases/conformance/enums/test-ts-enum-3.ts | 28 + .../enums/test-ts-enum-30-expected.txt | 2 + .../conformance/enums/test-ts-enum-30.ts | 33 + .../enums/test-ts-enum-31-expected.txt | 2 + .../conformance/enums/test-ts-enum-31.ts | 28 + .../enums/test-ts-enum-32-expected.txt | 2 + .../conformance/enums/test-ts-enum-32.ts | 34 + .../enums/test-ts-enum-33-expected.txt | 3 + .../conformance/enums/test-ts-enum-33.ts | 42 ++ .../enums/test-ts-enum-34-expected.txt | 2 + .../conformance/enums/test-ts-enum-34.ts | 27 + .../enums/test-ts-enum-35-expected.txt | 2 + .../conformance/enums/test-ts-enum-35.ts | 28 + .../enums/test-ts-enum-4-expected.txt | 1 + .../cases/conformance/enums/test-ts-enum-4.ts | 31 + .../enums/test-ts-enum-5-expected.txt | 1 + .../cases/conformance/enums/test-ts-enum-5.ts | 27 + .../enums/test-ts-enum-6-expected.txt | 2 + .../cases/conformance/enums/test-ts-enum-6.ts | 27 + .../enums/test-ts-enum-7-expected.txt | 1 + .../cases/conformance/enums/test-ts-enum-7.ts | 30 + .../enums/test-ts-enum-8-expected.txt | 1 + .../cases/conformance/enums/test-ts-enum-8.ts | 28 + .../enums/test-ts-enum-9-expected.txt | 1 + .../cases/conformance/enums/test-ts-enum-9.ts | 31 + .../ts/test-enum-declaration1-expected.txt | 117 +-- 91 files changed, 2201 insertions(+), 249 deletions(-) create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9.ts diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 6ad17db5ea..a5a97664bd 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -15,7 +15,6 @@ #include "binder.h" -#include #include #include #include @@ -44,11 +43,13 @@ #include #include #include +#include #include #include #include #include #include +#include namespace panda::es2panda::binder { void Binder::InitTopScope() @@ -262,7 +263,7 @@ void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *sc outerVarScope->AddFlag(VariableScopeFlags::INNER_ARROW); } - ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope()); + ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope()); BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(scriptFunc), scriptFunc); } @@ -604,6 +605,11 @@ void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode) ResolveReferences(childNode); break; } + case ir::AstNodeType::TS_ENUM_DECLARATION: { + auto scopeCtx = LexicalScope::Enter(this, childNode->AsTSEnumDeclaration()->Scope()); + ResolveReferences(childNode); + break; + } default: { ResolveReferences(childNode); break; @@ -680,17 +686,24 @@ void Binder::AddMandatoryParams() } } -void Binder::AddDeclarationName(const util::StringView &name) +void Binder::AddDeclarationName(const util::StringView &name, DeclType type) { if (extension_ != ScriptExtension::TS) { return; } variableNames_.insert(name); + + if (type == DeclType::ENUM) { + return; + } auto *scope = GetScope(); while (scope != nullptr) { if (scope->IsTSModuleScope()) { scope->AsTSModuleScope()->AddDeclarationName(name); } + if (scope->IsTSEnumScope()) { + scope->AsTSEnumScope()->AddDeclarationName(name); + } scope = scope->Parent(); } } diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 5d3edaaf95..a45d8a198d 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -123,7 +123,7 @@ public: return anonymousFunctionNames_; } - void AddDeclarationName(const util::StringView &name); + void AddDeclarationName(const util::StringView &name, DeclType type = DeclType::NONE); bool HasVariableName(const util::StringView &name) const; @@ -272,7 +272,7 @@ T *Binder::AddDecl(const lexer::SourcePosition &pos, Args &&... args) T *decl = Allocator()->New(std::forward(args)...); if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { - AddDeclarationName(decl->Name()); + AddDeclarationName(decl->Name(), decl->Type()); return decl; } @@ -286,7 +286,7 @@ T *Binder::AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, Args decl->AddFlag(flag); if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { - AddDeclarationName(decl->Name()); + AddDeclarationName(decl->Name(), decl->Type()); return decl; } diff --git a/es2panda/binder/declaration.h b/es2panda/binder/declaration.h index c835e99e5e..8e20c759a2 100644 --- a/es2panda/binder/declaration.h +++ b/es2panda/binder/declaration.h @@ -25,6 +25,7 @@ class AstNode; class ScriptFunction; class TSInterfaceDeclaration; class TSModuleDeclaration; +class TSEnumDeclaration; class ImportDeclaration; } // namespace panda::es2panda::ir @@ -32,6 +33,7 @@ namespace panda::es2panda::binder { class Scope; class LocalScope; +class TSEnumScope; #define DECLARE_CLASSES(decl_kind, className) class className; DECLARATION_KINDS(DECLARE_CLASSES) @@ -133,32 +135,46 @@ private: ArenaVector declarations_; }; -class EnumLiteralDecl : public Decl { +class EnumLiteralDecl : public MultiDecl { public: - explicit EnumLiteralDecl(util::StringView name, bool isConst) : Decl(name), isConst_(isConst) {} - + explicit EnumLiteralDecl(ArenaAllocator *allocator, util::StringView name, + bool isExport, bool isDeclare, bool isConst) : MultiDecl(allocator, name), + isExport_(isExport), isDeclare_(isDeclare), isConst_(isConst) {} + DeclType Type() const override { return DeclType::ENUM_LITERAL; } + bool IsExport() const + { + return isExport_; + } + + bool IsDeclare() const + { + return isDeclare_; + } + bool IsConst() const { return isConst_; } - void BindScope(LocalScope *scope) + void BindScope(TSEnumScope *scope) { scope_ = scope; } - LocalScope *Scope() + TSEnumScope *Scope() { return scope_; } private: - LocalScope *scope_ {}; + TSEnumScope *scope_ {nullptr}; + bool isExport_ {}; + bool isDeclare_ {}; bool isConst_ {}; }; diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index 696521f188..63e1295967 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -196,13 +196,9 @@ bool Scope::AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl return true; } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, VariableFlags::ENUM_LITERAL)}); - return true; + return tsBindings_.AddTSVariable( + newDecl->Name(), allocator->New(newDecl, VariableFlags::ENUM_LITERAL)); } case DeclType::INTERFACE: { bindings_.insert({newDecl->Name(), allocator->New(newDecl, VariableFlags::INTERFACE)}); @@ -298,12 +294,8 @@ bool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVaria case DeclType::FUNC: { return AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); @@ -320,6 +312,13 @@ bool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVaria } } +bool TSEnumScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, + [[maybe_unused]] ScriptExtension extension) +{ + ASSERT(newDecl->Type() == DeclType::ENUM); + return enumMemberBindings_->insert({newDecl->Name(), allocator->New(newDecl, false)}).second; +} + bool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, [[maybe_unused]] ScriptExtension extension) { @@ -330,12 +329,8 @@ bool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariabl case DeclType::FUNC: { return AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); @@ -401,12 +396,8 @@ bool ModuleScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariabl AddFunction(allocator, currentVariable, newDecl, extension) : AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 3fd392aef7..29c03a3297 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -806,6 +806,48 @@ private: ArenaSet variableNames_; }; +class TSEnumScope : public FunctionScope { +public: + explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope( + allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter()) + { + paramScope_ = allocator->New(allocator, parent); + paramScope_->BindFunctionScope(this); + SetParent(paramScope_); + } + + ScopeType Type() const override + { + return ScopeType::TSENUM; + } + + Variable *FindEnumMemberVariable(const util::StringView &name) const + { + auto res = enumMemberBindings_->find(name); + if (res == enumMemberBindings_->end()) { + return nullptr; + } + return res->second; + } + + void AddDeclarationName(const util::StringView &name) + { + variableNames_.insert(name); + } + + bool HasDeclarationName(const util::StringView &name) const + { + return variableNames_.find(name) != variableNames_.end(); + } + + bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, + [[maybe_unused]] ScriptExtension extension) override; + +private: + VariableMap *enumMemberBindings_; + ArenaSet variableNames_; +}; + inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag) { VariableFlags varFlag = VariableFlags::NONE; @@ -894,7 +936,7 @@ bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, Varia newDecl->Name(), allocator->New(newDecl, flags)); } case VariableFlags::ENUM_LITERAL: { - return tsBindings_.AddTSVariable( + return tsBindings_.AddTSVariable( newDecl->Name(), allocator->New(newDecl, flags)); } case VariableFlags::INTERFACE: { diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 7c82dd583c..0539c9ccc5 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -70,6 +70,7 @@ void ModuleVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] void EnumVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void NamespaceVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void ImportEqualsVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} +void EnumLiteralVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void EnumVariable::ResetDecl(Decl *decl) { diff --git a/es2panda/binder/variable.h b/es2panda/binder/variable.h index d9408beec3..170055cf16 100644 --- a/es2panda/binder/variable.h +++ b/es2panda/binder/variable.h @@ -35,6 +35,9 @@ class Decl; class Scope; class VariableScope; class ExportBindings; +class Variable; + +using VariableMap = ArenaUnorderedMap; #define DECLARE_CLASSES(type, className) class className; VARIABLE_TYPES(DECLARE_CLASSES) @@ -232,6 +235,26 @@ public: backReference_ = true; } + bool IsVisited() const + { + return isVisited_; + } + + void SetVisited() + { + isVisited_ = true; + } + + bool StringInit() const + { + return isStringInit_; + } + + void SetStringInit() + { + isStringInit_ = true; + } + void ResetDecl(Decl *decl); void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; @@ -239,6 +262,8 @@ public: private: EnumMemberResult value_ {false}; bool backReference_ {}; + bool isVisited_ {false}; + bool isStringInit_ {false}; }; class NamespaceVariable : public Variable { @@ -266,6 +291,40 @@ private: ExportBindings *exportBindings_ {nullptr}; }; +class EnumLiteralVariable : public Variable { +public: + explicit EnumLiteralVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} + + VariableType Type() const override + { + return VariableType::ENUMLITERAL; + } + + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + + VariableMap *GetEnumMembers() const + { + return enumMemberBindings_; + } + + Variable *FindEnumMemberVariable(const util::StringView &name) const + { + auto res = enumMemberBindings_->find(name); + if (res == enumMemberBindings_->end()) { + return nullptr; + } + return res->second; + } + + void SetEnumMembers(VariableMap *enumMemberBindings) + { + enumMemberBindings_ = enumMemberBindings; + } + +private: + VariableMap *enumMemberBindings_ {nullptr}; +}; + class ImportEqualsVariable : public Variable { public: explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} diff --git a/es2panda/binder/variableFlags.h b/es2panda/binder/variableFlags.h index cc60c28879..4d0d465663 100644 --- a/es2panda/binder/variableFlags.h +++ b/es2panda/binder/variableFlags.h @@ -58,7 +58,8 @@ enum class DeclType { _(FUNCTION, FunctionScope) \ _(GLOBAL, GlobalScope) \ _(MODULE, ModuleScope) \ - _(TSMODULE, TSModuleScope) + _(TSMODULE, TSModuleScope) \ + _(TSENUM, TSEnumScope) enum class ScopeType { @@ -89,7 +90,8 @@ DEFINE_BITOPS(ResolveBindingFlags) _(MODULE, ModuleVariable) \ _(ENUM, EnumVariable) \ _(NAMESPACE, NamespaceVariable) \ - _(IMPORT_EQUALS, ImportEqualsVariable) + _(IMPORT_EQUALS, ImportEqualsVariable) \ + _(ENUMLITERAL, EnumLiteralVariable) enum class VariableType { #define GEN_VARIABLE_TYPES(type, class_name) type, @@ -167,7 +169,7 @@ DEFINE_BITOPS(DeclarationFlags) enum class TSBindingType : size_t { NAMESPACE = 0, - ENUM, + ENUMLITERAL, INTERFACE, IMPORT_EQUALS, COUNT, diff --git a/es2panda/compiler/base/hoisting.cpp b/es2panda/compiler/base/hoisting.cpp index 2bf9a660b6..741c6f08fd 100644 --- a/es2panda/compiler/base/hoisting.cpp +++ b/es2panda/compiler/base/hoisting.cpp @@ -70,7 +70,7 @@ static void HoistFunction(PandaGen *pg, binder::Variable *var, const binder::Fun } ASSERT(scope->IsFunctionScope() || scope->IsCatchScope() || scope->IsLocalScope() || - scope->IsModuleScope() || scope->IsTSModuleScope()); + scope->IsModuleScope() || scope->IsTSModuleScope() || scope->IsTSEnumScope()); binder::ScopeFindResult result(decl->Name(), scope, 0, var); pg->DefineFunction(decl->Node(), scriptFunction, internalName); diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index 80bd914fa0..9143ac1ca2 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -193,7 +193,7 @@ static void CompileFunctionOrProgram(PandaGen *pg) } else { pg->FunctionInit(nullptr); - if (topScope->IsFunctionScope() || topScope->IsTSModuleScope()) { + if (topScope->IsFunctionScope() || topScope->IsTSModuleScope() || topScope->IsTSEnumScope()) { CompileFunction(pg); } else { ASSERT(topScope->IsGlobalScope() || topScope->IsModuleScope()); diff --git a/es2panda/ir/expressions/binaryExpression.h b/es2panda/ir/expressions/binaryExpression.h index 8ac98c5c57..0fb29f1d63 100644 --- a/es2panda/ir/expressions/binaryExpression.h +++ b/es2panda/ir/expressions/binaryExpression.h @@ -52,6 +52,11 @@ public: return right_; } + Expression *Right() + { + return right_; + } + lexer::TokenType OperatorType() const { return operator_; diff --git a/es2panda/ir/expressions/memberExpression.h b/es2panda/ir/expressions/memberExpression.h index a38b20dfb2..74a7e17bc1 100644 --- a/es2panda/ir/expressions/memberExpression.h +++ b/es2panda/ir/expressions/memberExpression.h @@ -51,6 +51,11 @@ public: return object_; } + Expression *Object() + { + return object_; + } + const Expression *Property() const { return property_; diff --git a/es2panda/ir/ts/tsEnumDeclaration.cpp b/es2panda/ir/ts/tsEnumDeclaration.cpp index e75142f597..1e5cfd67ab 100644 --- a/es2panda/ir/ts/tsEnumDeclaration.cpp +++ b/es2panda/ir/ts/tsEnumDeclaration.cpp @@ -261,15 +261,15 @@ void AddEnumValueDeclaration(checker::Checker *checker, double number, binder::E util::StringView memberStr = util::Helpers::ToStringView(checker->Allocator(), number); - binder::LocalScope *enumScope = checker->Scope()->AsLocalScope(); - binder::Variable *res = enumScope->FindLocal(memberStr); + binder::TSEnumScope *enumScope = checker->Scope()->AsTSEnumScope(); + binder::Variable *res = enumScope->FindEnumMemberVariable(memberStr); binder::EnumVariable *enumVar = nullptr; if (!res) { auto *decl = checker->Allocator()->New(memberStr); decl->BindNode(variable->Declaration()->Node()); enumScope->AddDecl(checker->Allocator(), decl, ScriptExtension::TS); - res = enumScope->FindLocal(memberStr); + res = enumScope->FindEnumMemberVariable(memberStr); ASSERT(res && res->IsEnumVariable()); enumVar = res->AsEnumVariable(); enumVar->AsEnumVariable()->SetBackReference(); @@ -360,7 +360,7 @@ checker::Type *TSEnumDeclaration::InferType(checker::Checker *checker, bool isCo { double value = -1.0; - binder::LocalScope *enumScope = checker->Scope()->AsLocalScope(); + binder::TSEnumScope *enumScope = checker->Scope()->AsTSEnumScope(); bool initNext = false; bool isLiteralEnum = false; @@ -369,7 +369,7 @@ checker::Type *TSEnumDeclaration::InferType(checker::Checker *checker, bool isCo for (size_t i = 0; i < localsSize; i++) { const util::StringView ¤tName = enumScope->Decls()[i]->Name(); - binder::Variable *currentVar = enumScope->FindLocal(currentName); + binder::Variable *currentVar = enumScope->FindEnumMemberVariable(currentName); ASSERT(currentVar && currentVar->IsEnumVariable()); InferEnumVariableType(checker, currentVar->AsEnumVariable(), &value, &initNext, &isLiteralEnum, isConst, computedExpr); @@ -386,7 +386,10 @@ checker::Type *TSEnumDeclaration::InferType(checker::Checker *checker, bool isCo checker::Type *TSEnumDeclaration::Check(checker::Checker *checker) const { binder::Variable *enumVar = key_->Variable(); - ASSERT(enumVar); + // TODO: enumLiteral Identifier binds enumLiteral Variable. + if (enumVar == nullptr) { + return nullptr; + } if (!enumVar->TsType()) { checker::ScopeContext scopeCtx(checker, scope_); diff --git a/es2panda/ir/ts/tsEnumDeclaration.h b/es2panda/ir/ts/tsEnumDeclaration.h index b1920b0243..91ced8eb65 100644 --- a/es2panda/ir/ts/tsEnumDeclaration.h +++ b/es2panda/ir/ts/tsEnumDeclaration.h @@ -40,17 +40,19 @@ class TSEnumMember; class TSEnumDeclaration : public Statement { public: - explicit TSEnumDeclaration(binder::LocalScope *scope, Identifier *key, ArenaVector &&members, - bool isConst) + explicit TSEnumDeclaration(binder::TSEnumScope *scope, Identifier *key, ArenaVector &&members, + bool isExport, bool isDeclare, bool isConst) : Statement(AstNodeType::TS_ENUM_DECLARATION), scope_(scope), key_(key), members_(std::move(members)), + isExport_(isExport), + isDeclare_(isDeclare), isConst_(isConst) { } - binder::LocalScope *Scope() const + binder::TSEnumScope *Scope() const { return scope_; } @@ -65,6 +67,16 @@ public: return members_; } + bool IsExport() const + { + return isExport_; + } + + bool IsDeclare() const + { + return isDeclare_; + } + bool IsConst() const { return isConst_; @@ -81,9 +93,11 @@ public: void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; private: - binder::LocalScope *scope_; + binder::TSEnumScope *scope_; Identifier *key_; ArenaVector members_; + bool isExport_; + bool isDeclare_; bool isConst_; }; diff --git a/es2panda/ir/ts/tsEnumMember.h b/es2panda/ir/ts/tsEnumMember.h index 4f6d28ba5d..edd6ef7d8f 100644 --- a/es2panda/ir/ts/tsEnumMember.h +++ b/es2panda/ir/ts/tsEnumMember.h @@ -47,6 +47,12 @@ public: { return init_; } + + Expression *Init() + { + return init_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index c1af0bba70..26d526d345 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2855,7 +2855,7 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i } ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart, - bool isConst) + bool isExport, bool isDeclare, bool isConst) { if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { ThrowSyntaxError("'{' expected"); @@ -2875,8 +2875,8 @@ ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const l memberKey->SetRange(lexer_->GetToken().Loc()); lexer_->NextToken(); } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) { - decl = Binder()->AddDecl(keyStartLoc, lexer_->GetToken().String()); memberKey = AllocNode(lexer_->GetToken().String()); + decl = Binder()->AddDecl(keyStartLoc, lexer_->GetToken().String()); memberKey->SetRange(lexer_->GetToken().Loc()); lexer_->NextToken(); } else { @@ -2902,8 +2902,8 @@ ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const l } } - auto *enumDeclaration = - AllocNode(Binder()->GetScope()->AsLocalScope(), key, std::move(members), isConst); + auto *enumDeclaration = AllocNode( + Binder()->GetScope()->AsTSEnumScope(), key, std::move(members), isExport, isDeclare, isConst); enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()}); Binder()->GetScope()->BindNode(enumDeclaration); lexer_->NextToken(); // eat '}' @@ -2911,7 +2911,7 @@ ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const l return enumDeclaration; } -ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isConst) +ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDeclare, bool isConst) { ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM); lexer::SourcePosition enumStart = lexer_->GetToken().Start(); @@ -2922,33 +2922,40 @@ ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isConst) } const util::StringView &ident = lexer_->GetToken().Ident(); - binder::TSBinding tsBinding(Allocator(), ident); + auto *currentScope = Binder()->GetScope(); + binder::Variable *res = currentScope->FindLocalTSVariable(ident); + if (res == nullptr && isExport && currentScope->IsTSModuleScope()) { + res = currentScope->AsTSModuleScope()->FindExportTSVariable(ident); + if (res != nullptr) { + currentScope->AddLocalTSVariable(ident, res); + } + } + if (res == nullptr) { + Binder()->AddTsDecl(lexer_->GetToken().Start(), Allocator(), + ident, isExport, isDeclare, isConst); + res = currentScope->FindLocalTSVariable(ident); + if (isExport && currentScope->IsTSModuleScope()) { + currentScope->AsTSModuleScope()->AddExportTSVariable(ident, res); + } + res->AsEnumLiteralVariable()->SetEnumMembers(Allocator()->New(Allocator()->Adapter())); + } + binder::VariableMap *enumMemberBindings = res->AsEnumLiteralVariable()->GetEnumMembers(); auto *key = AllocNode(ident, Allocator()); key->SetRange(lexer_->GetToken().Loc()); key->SetReference(); lexer_->NextToken(); - const auto &bindings = Binder()->GetScope()->Bindings(); - auto res = bindings.find(tsBinding.View()); - binder::EnumLiteralDecl *decl {}; - - if (res == bindings.end()) { - decl = Binder()->AddTsDecl(lexer_->GetToken().Start(), tsBinding.View(), isConst); - binder::LexicalScope enumCtx = binder::LexicalScope(Binder()); - decl->AsEnumLiteralDecl()->BindScope(enumCtx.GetScope()); - return ParseEnumMembers(key, enumStart, isConst); - } - - if (!res->second->Declaration()->IsEnumLiteralDecl() || - (isConst ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst())) { + if (!res->Declaration()->IsEnumLiteralDecl() || + (isConst ^ res->Declaration()->AsEnumLiteralDecl()->IsConst())) { Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident); } - decl = res->second->Declaration()->AsEnumLiteralDecl(); - - auto scopeCtx = binder::LexicalScope::Enter(Binder(), decl->Scope()); - return ParseEnumMembers(key, enumStart, isConst); + auto enumCtx = binder::LexicalScope(Binder(), enumMemberBindings); + auto *enumDeclaration = ParseEnumMembers(key, enumStart, isExport, isDeclare, isConst); + res->Declaration()->AsEnumLiteralDecl()->Add(enumDeclaration); + + return enumDeclaration; } void ParserImpl::ValidateFunctionParam(const ArenaVector ¶ms, const ir::Expression *parameter, diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index fc1663e5e9..94a64af6b1 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -484,8 +484,9 @@ private: bool isDeclare = false, bool isAbstract = false, bool isExported = false); ir::TSTypeAliasDeclaration *ParseTsTypeAliasDeclaration(bool isDeclare); - ir::TSEnumDeclaration *ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart, bool isConst); - ir::TSEnumDeclaration *ParseEnumDeclaration(bool isConst = false); + ir::TSEnumDeclaration *ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart, + bool isExport, bool isDeclare, bool isConst); + ir::TSEnumDeclaration *ParseEnumDeclaration(bool isExport = false, bool isDeclare = false, bool isConst = false); ir::TSInterfaceDeclaration *ParseTsInterfaceDeclaration(); ir::SwitchCaseStatement *ParseSwitchCaseStatement(bool *seenDefault); ir::SwitchStatement *ParseSwitchStatement(); @@ -498,7 +499,7 @@ private: const lexer::SourcePosition &startLoc, bool isDeclare); ir::VariableDeclarator *ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare); ir::Statement *ParseVariableDeclaration(VariableParsingFlags flags = VariableParsingFlags::NO_OPTS, - bool isDeclare = false); + bool isDeclare = false, bool isExport = false); ir::WhileStatement *ParseWhileStatement(); ir::VariableDeclaration *ParseContextualLet(VariableParsingFlags flags, StatementParsingFlags stmFlags = StatementParsingFlags::ALLOW_LEXICAL, diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index aea10c255c..704e029e3d 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -510,7 +510,7 @@ ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags, bool if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) { if (Extension() == ScriptExtension::TS) { - return ParseEnumDeclaration(true); + return ParseEnumDeclaration(false, isDeclare, true); } ThrowSyntaxError("Unexpected token"); } @@ -575,7 +575,7 @@ ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFla if (Extension() == ScriptExtension::TS) { switch (lexer_->GetToken().KeywordType()) { case lexer::TokenType::KEYW_ENUM: { - return ParseEnumDeclaration(); + return ParseEnumDeclaration(false, isDeclare, false); } case lexer::TokenType::KEYW_TYPE: { return ParseTsTypeAliasDeclaration(isDeclare); @@ -1982,7 +1982,7 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags return declarator; } -ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare) +ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport) { lexer::SourcePosition startLoc = lexer_->GetToken().Start(); @@ -1999,7 +1999,7 @@ ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, if (!(flags & VariableParsingFlags::CONST)) { ThrowSyntaxError("Variable declaration expected."); } - return ParseEnumDeclaration(true); + return ParseEnumDeclaration(isExport, isDeclare, true); } ArenaVector declarators(Allocator()->Adapter()); @@ -2427,15 +2427,15 @@ ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer: switch (lexer_->GetToken().Type()) { case lexer::TokenType::KEYW_VAR: { - decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare); + decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true); break; } case lexer::TokenType::KEYW_CONST: { - decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare); + decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true); break; } case lexer::TokenType::KEYW_LET: { - decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare); + decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true); break; } case lexer::TokenType::KEYW_FUNCTION: { @@ -2454,7 +2454,7 @@ ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer: break; } case lexer::TokenType::KEYW_ENUM: { - decl = ParseEnumDeclaration(); + decl = ParseEnumDeclaration(true, isDeclare, false); break; } case lexer::TokenType::KEYW_INTERFACE: { diff --git a/es2panda/parser/transformer/transformer.cpp b/es2panda/parser/transformer/transformer.cpp index bb0825beea..6726e1be61 100644 --- a/es2panda/parser/transformer/transformer.cpp +++ b/es2panda/parser/transformer/transformer.cpp @@ -17,11 +17,13 @@ #include +#include "binder/scope.h" #include "ir/base/classDefinition.h" #include "ir/base/classProperty.h" #include "ir/base/decorator.h" #include "ir/base/methodDefinition.h" #include "ir/base/scriptFunction.h" +#include "ir/base/templateElement.h" #include "ir/expressions/assignmentExpression.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/callExpression.h" @@ -34,8 +36,10 @@ #include "ir/expressions/memberExpression.h" #include "ir/expressions/objectExpression.h" #include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/templateLiteral.h" #include "ir/expressions/thisExpression.h" #include "ir/module/exportNamedDeclaration.h" +#include "ir/module/exportSpecifier.h" #include "ir/statements/blockStatement.h" #include "ir/statements/classDeclaration.h" #include "ir/statements/emptyStatement.h" @@ -43,6 +47,8 @@ #include "ir/statements/functionDeclaration.h" #include "ir/statements/variableDeclaration.h" #include "ir/statements/variableDeclarator.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsEnumMember.h" #include "ir/ts/tsImportEqualsDeclaration.h" #include "ir/ts/tsModuleBlock.h" #include "ir/ts/tsModuleDeclaration.h" @@ -183,19 +189,22 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) switch (childNode->Type()) { case ir::AstNodeType::IDENTIFIER: { auto *ident = childNode->AsIdentifier(); - if (!ident->IsReference() || !IsTsModule()) { + if (!ident->IsReference() || (!IsTsModule() && !IsTsEnum())) { return VisitTSNodes(childNode); } auto name = ident->Name(); - auto scope = FindExportVariableInTsModuleScope(name); - if (scope) { - auto moduleName = FindTSModuleNameByScope(scope); - auto *id = CreateReferenceIdentifier(moduleName); - auto *res = AllocNode(id, AllocNode(name, Allocator()), - ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); - SetOriginalNode(res, childNode); - return res; + if (IsTsEnum()) { + auto scope = FindEnumMemberScope(name); + if (scope) { + return CreateMemberExpressionFromIdentifier(scope, ident); + } + } + if (IsTsModule()) { + auto scope = FindExportVariableInTsModuleScope(name); + if (scope) { + return CreateMemberExpressionFromIdentifier(scope, ident); + } } return VisitTSNodes(childNode); @@ -209,6 +218,15 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) SetOriginalNode(res, childNode); return res; } + case ir::AstNodeType::TS_ENUM_DECLARATION: { + auto *node = childNode->AsTSEnumDeclaration(); + if (node->IsDeclare()) { + return childNode; + } + auto res = VisitTsEnumDeclaration(node); + SetOriginalNode(res, childNode); + return res; + } case ir::AstNodeType::EXPORT_NAMED_DECLARATION: { auto *node = childNode->AsExportNamedDeclaration(); auto *decl = node->Decl(); @@ -226,6 +244,15 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) return res; } + if (decl->IsTSEnumDeclaration()) { + if (decl->AsTSEnumDeclaration()->IsDeclare()) { + return childNode; + } + auto res = VisitTsEnumDeclaration(decl->AsTSEnumDeclaration(), true); + SetOriginalNode(res, childNode); + return res; + } + if (!IsTsModule()) { return VisitTSNodes(childNode); } @@ -848,7 +875,7 @@ std::vector Transformer::CreateClassDecorators(ir::ClassDeclarati ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node) { auto *express = node->ModuleReference(); - if (!IsInstantiatedTSModule(express)) { + if (!IsInstantiatedTSModule(express, Scope())) { return node; } auto name = node->Id()->Name(); @@ -875,9 +902,9 @@ ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDecla return res; } -bool Transformer::IsInstantiatedTSModule(const ir::Expression *node) const +bool Transformer::IsInstantiatedTSModule(const ir::Expression *node, binder::Scope *scope) const { - auto *var = FindTSModuleVariable(node, Scope()); + auto *var = FindTSModuleVariable(node, scope); if (var == nullptr) { return true; } @@ -1058,12 +1085,21 @@ ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util return declaration; } -util::StringView Transformer::GetParamName(ir::TSModuleDeclaration *node, util::StringView name) const +util::StringView Transformer::GetParamName(ir::AstNode *node, util::StringView name) const { - auto scope = node->Scope(); - if (!scope->HasVariableName(name)) { - return name; + if (node->IsTSModuleDeclaration()) { + auto scope = node->AsTSModuleDeclaration()->Scope(); + if (scope && !scope->HasVariableName(name)) { + return name; + } + } + if (node->IsTSEnumDeclaration()) { + auto scope = node->AsTSEnumDeclaration()->Scope(); + if (scope && !scope->HasDeclarationName(name)) { + return name; + } } + auto uniqueName = CreateUniqueName(std::string(name) + std::string(INDEX_DIVISION)); return uniqueName; } @@ -1115,25 +1151,7 @@ ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDec auto *funcExpr = AllocNode(funcNode); - ArenaVector arguments(Allocator()->Adapter()); - ArenaVector properties(Allocator()->Adapter()); - auto *objectExpression = AllocNode(ir::AstNodeType::OBJECT_EXPRESSION, - std::move(properties), - false); - auto assignExpr = AllocNode(CreateTsModuleParam(name, isExport), - objectExpression, - lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - auto argument = AllocNode(CreateTsModuleParam(name, isExport), - assignExpr, - lexer::TokenType::PUNCTUATOR_LOGICAL_OR); - if (isExport) { - auto *id = CreateReferenceIdentifier(name); - arguments.push_back(AllocNode(id, argument, - lexer::TokenType::PUNCTUATOR_SUBSTITUTION)); - } else { - arguments.push_back(argument); - } - + ArenaVector arguments = CreateCallExpressionArguments(name, isExport); auto *callExpr = AllocNode(funcExpr, std::move(arguments), nullptr, false); return callExpr; @@ -1168,19 +1186,7 @@ ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *n auto findRes = Scope()->FindLocal(name, binder::ResolveBindingOptions::ALL); if (findRes == nullptr) { - bool doExport = isExport && !IsTsModule(); - auto flag = VariableParsingFlags::VAR; - if (IsTsModule()) { - flag = VariableParsingFlags::LET; - } - auto *var = CreateVariableDeclarationWithIdentify(name, flag, node, doExport); - if (doExport) { - ArenaVector specifiers(Allocator()->Adapter()); - res.push_back(AllocNode(var, std::move(specifiers))); - AddExportLocalEntryItem(name, node->Name()->AsIdentifier()); - } else { - res.push_back(var); - } + res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport)); } auto *callExpr = CreateCallExpressionForTsModule(node, name, isExport && IsTsModule()); @@ -1197,4 +1203,603 @@ ir::Identifier *Transformer::CreateReferenceIdentifier(util::StringView name) return node; } +ir::UpdateNodes Transformer::VisitTsEnumDeclaration(ir::TSEnumDeclaration *node, bool isExport) +{ + std::vector res; + + util::StringView name = GetNameFromTsEnumDeclaration(node); + + auto findRes = Scope()->FindLocal(name); // Find if the variable with the same name is already defined + if (findRes == nullptr) { + res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport)); + } + + auto *callExpr = CreateCallExpressionForTsEnum(node, name, isExport && IsTsModule()); + auto *exprStatementNode = AllocNode(callExpr); + res.push_back(exprStatementNode); + + return res; +} + +ir::AstNode *Transformer::CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name, + ir::AstNode *node, bool isExport) +{ + auto flag = Scope()->Parent() == nullptr ? VariableParsingFlags::VAR : VariableParsingFlags::LET; + auto *variableDeclaration = CreateVariableDeclarationWithIdentify(name, flag, node, isExport); + bool doExport = isExport && !IsTsModule(); + if (doExport) { // export var + ArenaVector specifiers(Allocator()->Adapter()); + auto *exportDeclaration = AllocNode(variableDeclaration, std::move(specifiers)); + auto *ident = node->IsTSEnumDeclaration() ? + node->AsTSEnumDeclaration()->Key()->AsIdentifier() : node->AsTSModuleDeclaration()->Name()->AsIdentifier(); + AddExportLocalEntryItem(name, ident); + return exportDeclaration; + } + return variableDeclaration; +} + +util::StringView Transformer::GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration *node) const +{ + auto *name = node->AsTSEnumDeclaration()->Key(); + return name->AsIdentifier()->Name(); +} + +ir::CallExpression *Transformer::CreateCallExpressionForTsEnum(ir::TSEnumDeclaration *node, util::StringView name, + bool isExport) +{ + ir::ScriptFunction *funcNode = nullptr; + + binder::FunctionScope *funcScope = node->Scope(); + binder::FunctionParamScope *funcParamScope = funcScope->ParamScope(); + util::StringView paramName = GetParamName(node, name); // modify the name of the function param + { + auto paramScopeCtx = binder::LexicalScope::Enter(Binder(), funcParamScope); + // create function param + ArenaVector params(Allocator()->Adapter()); + auto *parameter = CreateReferenceIdentifier(paramName); + Binder()->AddParamDecl(parameter); + params.push_back(parameter); + // create function body + ir::BlockStatement *blockNode = nullptr; + { + auto scopeCtx = binder::LexicalScope::Enter(Binder(), funcScope); + tsEnumList_.push_back({paramName, funcScope}); + + ArenaVector members = node->Members(); + ArenaVector statements(Allocator()->Adapter()); + ir::TSEnumMember *preTsEnumMember = nullptr; + for (auto member : members) { + auto *currTsEnumMember = member->AsTSEnumMember(); + auto statement = CreateTsEnumMember(currTsEnumMember, preTsEnumMember, paramName); + preTsEnumMember = currTsEnumMember; + statements.push_back(statement); + } + + blockNode = AllocNode(funcScope, std::move(statements)); + tsEnumList_.pop_back(); + funcScope->AddBindsFromParam(); + } + funcNode = AllocNode(funcScope, std::move(params), nullptr, blockNode, nullptr, + ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS); + + funcScope->BindNode(funcNode); + funcParamScope->BindNode(funcNode); + } + auto *funcExpr = AllocNode(funcNode); + + ArenaVector arguments = CreateCallExpressionArguments(name, isExport); + auto *callExpr = AllocNode(funcExpr, std::move(arguments), nullptr, false); + + return callExpr; +} + +ArenaVector Transformer::CreateCallExpressionArguments(util::StringView name, bool isExport) +{ + ArenaVector arguments(Allocator()->Adapter()); + ArenaVector properties(Allocator()->Adapter()); + auto *objectExpression = AllocNode(ir::AstNodeType::OBJECT_EXPRESSION, + std::move(properties), + false); + auto assignExpr = AllocNode(CreateTsModuleParam(name, isExport), + objectExpression, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto argument = AllocNode(CreateTsModuleParam(name, isExport), + assignExpr, + lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + if (isExport) { + auto *id = CreateReferenceIdentifier(name); + arguments.push_back(AllocNode(id, argument, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION)); + } else { + arguments.push_back(argument); + } + + return arguments; +} + +ir::ExpressionStatement *Transformer::CreateTsEnumMember(ir::TSEnumMember *node, ir::TSEnumMember *preNode, + util::StringView enumLiteralName) +{ + util::StringView enumMemberName = GetNameFromEnumMember(node); + binder::Variable *enumVar = Scope()->AsTSEnumScope()->FindEnumMemberVariable(enumMemberName); + ASSERT(enumVar); + if (node->Init() != nullptr) { + bool isStringInit = enumVar->AsEnumVariable()->StringInit(); + if (!enumVar->AsEnumVariable()->IsVisited()) { + isStringInit = IsStringInitForEnumMember(node->Init(), Scope()); + if (isStringInit) { + enumVar->AsEnumVariable()->SetStringInit(); + } + enumVar->AsEnumVariable()->SetVisited(); + } + return isStringInit ? CreateTsEnumMemberWithStringInit(node, enumLiteralName, enumMemberName) : + CreateTsEnumMemberWithNumberInit(node, enumLiteralName, enumMemberName); + } + + enumVar->AsEnumVariable()->SetVisited(); + return CreateTsEnumMemberWithoutInit(node, preNode, enumLiteralName, enumMemberName); +} + +ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithStringInit(ir::TSEnumMember *node, + util::StringView enumLiteralName, + util::StringView enumMemberName) +{ + // transform to the shape like E["a"] = "str"; + auto *object = CreateReferenceIdentifier(enumLiteralName); + auto *property = AllocNode(enumMemberName); + auto *left = AllocNode(object, property, + ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + auto *right = std::get(VisitTSNode(node->Init()))->AsExpression(); + + auto *assignExpr = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *exprStatementNode = AllocNode(assignExpr); + + return exprStatementNode; +} + +ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithNumberInit(ir::TSEnumMember *node, + util::StringView enumLiteralName, + util::StringView enumMemberName) +{ + // transform to the shape like E[E["a"] = init] = "a"; + auto *innerObject = CreateReferenceIdentifier(enumLiteralName); + auto *innerProperty = AllocNode(enumMemberName); + auto *innerLeft = AllocNode(innerObject, innerProperty, + ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + auto *innerRight = std::get(VisitTSNode(node->Init()))->AsExpression(); + + auto *object = CreateReferenceIdentifier(enumLiteralName); + auto *property = AllocNode(innerLeft, innerRight, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *left = AllocNode(object, property, + ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *right = AllocNode(enumMemberName); + + auto *assignExpr = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *exprStatementNode = AllocNode(assignExpr); + + return exprStatementNode; +} + +ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithoutInit(ir::TSEnumMember *node, + ir::TSEnumMember *preNode, + util::StringView enumLiteralName, + util::StringView enumMemberName) +{ + // transform to the shape like E[E["a"] = value] = "a"; + auto *innerObject = CreateReferenceIdentifier(enumLiteralName); + auto *innerProperty = AllocNode(enumMemberName); + auto *innerLeft = AllocNode(innerObject, innerProperty, + ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + ir::AssignmentExpression *property = nullptr; + if (preNode == nullptr) { // first enumMember, value = 0 + auto *innerRight = AllocNode(0); + property = AllocNode(innerLeft, innerRight, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + } else { // not first enumMember, value = E.prenode + 1 + auto *innerRightObject = CreateReferenceIdentifier(enumLiteralName); + auto *innerPropertyForMemberExpr = AllocNode(GetNameFromEnumMember(preNode), Allocator()); + auto *innerMemberExpr = AllocNode(innerRightObject, innerPropertyForMemberExpr, + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto *innerRight = AllocNode(innerMemberExpr, AllocNode(1), + lexer::TokenType::PUNCTUATOR_PLUS); + property = AllocNode(innerLeft, innerRight, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + } + auto *object = CreateReferenceIdentifier(enumLiteralName); + auto *left = AllocNode(object, property, + ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *right = AllocNode(enumMemberName); + + auto *assignExpr = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *exprStatementNode = AllocNode(assignExpr); + + return exprStatementNode; +} + +bool Transformer::IsStringInitForEnumMember(const ir::Expression *expr, binder::Scope *scope) const +{ + if (expr == nullptr) { + return false; + } + + // The string enumMember is either initialized with a string literal, or with another string enumMember. + switch (expr->Type()) { + case ir::AstNodeType::STRING_LITERAL: + case ir::AstNodeType::TEMPLATE_LITERAL: { + // TemplateLiteral in Enum must be a string literal. + return true; + } + case ir::AstNodeType::IDENTIFIER: { + // Return true if this identifier is a string enumMember of the current Enum. + util::StringView identName = expr->AsIdentifier()->Name(); + ASSERT(scope && scope->IsTSEnumScope()); + binder::Variable *v = scope->AsTSEnumScope()->FindEnumMemberVariable(identName); + if (v == nullptr) { + return false; + } + if (!v->AsEnumVariable()->IsVisited()) { // visit the quoted item + auto *initExpr = v->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init(); + if (IsStringInitForEnumMember(initExpr, scope)) { + v->AsEnumVariable()->SetStringInit(); + } + v->AsEnumVariable()->SetVisited(); + } + if (v->AsEnumVariable()->IsVisited() && v->AsEnumVariable()->StringInit()) { + return true; + } + + return false; + } + case ir::AstNodeType::MEMBER_EXPRESSION: { + return IsStringForMemberExpression(expr->AsMemberExpression(), scope); + } + case ir::AstNodeType::BINARY_EXPRESSION: { + auto *left = expr->AsBinaryExpression()->Left(); + auto *right = expr->AsBinaryExpression()->Right(); + if (expr->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS && + IsStringInitForEnumMember(right, scope) && IsStringInitForEnumMember(left, scope)) { + return true; + } + return false; + } + default: + return false; + } + + return false; +} + +bool Transformer::IsStringForMemberExpression(const ir::MemberExpression *memberExpr, binder::Scope *scope) const +{ + // Return true only if memberExpression is a string enumMember. + const ir::Expression *expr = memberExpr; + ArenaDeque members(Allocator()->Adapter()); + while (expr->IsMemberExpression()) { + if (expr->AsMemberExpression()->Property()->IsIdentifier() || + expr->AsMemberExpression()->Property()->IsStringLiteral() || + expr->AsMemberExpression()->Property()->IsTemplateLiteral()) { + members.push_front(expr->AsMemberExpression()->Property()); + expr = expr->AsMemberExpression()->Object(); + } else { + return false; + } + } + if (!expr->IsIdentifier()) { + return false; + } + members.push_front(expr->AsIdentifier()); + + // Find front Ident TSVariables + ArenaVector findRes = FindFrontIdentifierTSVariables(members.front()->AsIdentifier(), scope); + members.pop_front(); + + for (auto currVar : findRes) { + if (VerifyMemberExpressionDeque(currVar, members)) { + return true; + } + } + return false; +} + +ArenaVector Transformer::FindFrontIdentifierTSVariables(const ir::Identifier *ident, + binder::Scope *scope) const +{ + util::StringView name = ident->Name(); + binder::Variable *v = nullptr; + ArenaVector findRes(Allocator()->Adapter()); + while (scope != nullptr) { + // find enumMemberBindings_ + if (scope->IsTSEnumScope()) { + v = scope->AsTSEnumScope()->FindEnumMemberVariable(name); + if (v != nullptr) { + break; + } + } + + const std::vector types = {binder::TSBindingType::NAMESPACE, + binder::TSBindingType::ENUMLITERAL, + binder::TSBindingType::IMPORT_EQUALS}; + // find tsBindings_ + FindLocalTSVariables(scope, name, types, findRes); + // find exportTSBindings_ + if (scope->IsTSModuleScope()) { + FindExportTSVariables(scope, name, types, findRes); + } + + if (!findRes.empty()) { + break; + } + + // find js variable + v = scope->FindLocal(name); + if (v != nullptr) { + if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { // v may be converted from ts variable + v = scope->Parent()->FindLocal(name); + if (v == nullptr) { + break; + } + } else { + break; + } + } + if (scope->IsTSModuleScope()) { + v = scope->AsTSModuleScope()->FindExportVariable(name); + if (v != nullptr) { + break; + } + } + + if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { + scope = scope->Parent(); + } + scope = scope->Parent(); + } + + return findRes; +} + +bool Transformer::IsInstantiatedNamespaceVariable(binder::Variable *var) const +{ + ASSERT(var->IsNamespaceVariable()); + auto *decl = var->AsNamespaceVariable()->Declaration(); + ASSERT(decl->IsNamespaceDecl()); + ArenaVector nodes = decl->AsNamespaceDecl()->Decls(); + for (ir::TSModuleDeclaration *node : nodes) { + if (node->IsInstantiated()) { + return true; + } + } + return false; +} + +void Transformer::FindLocalTSVariables(binder::Scope *scope, const util::StringView name, + const std::vector &types, + ArenaVector &findRes) const +{ + for (binder::TSBindingType type : types) { + binder::Variable *v = nullptr; + switch (type) { + case binder::TSBindingType::NAMESPACE: { + v = scope->FindLocalTSVariable(name); + if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) { + v = nullptr; + } + break; + } + case binder::TSBindingType::ENUMLITERAL: { + v = scope->FindLocalTSVariable(name); + break; + } + case binder::TSBindingType::IMPORT_EQUALS: { + v = scope->FindLocalTSVariable(name); + if (v != nullptr && + !IsInstantiatedTSModule(v->AsImportEqualsVariable()->Declaration()->Node()-> + Parent()->AsTSImportEqualsDeclaration()->ModuleReference(), scope)) { + v = nullptr; + } + break; + } + default: + continue; + } + if (v != nullptr) { + findRes.push_back(v); + } + } +} + +void Transformer::FindExportTSVariables(binder::Scope *scope, const util::StringView name, + const std::vector &types, + ArenaVector &findRes) const +{ + for (binder::TSBindingType type : types) { + binder::Variable *v = nullptr; + switch (type) { + case binder::TSBindingType::NAMESPACE: { + v = scope->AsTSModuleScope()->FindExportTSVariable(name); + if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) { + v = nullptr; + } + break; + } + case binder::TSBindingType::ENUMLITERAL: { + v = scope->AsTSModuleScope()->FindExportTSVariable(name); + break; + } + case binder::TSBindingType::IMPORT_EQUALS: { + v = scope->AsTSModuleScope()->FindExportTSVariable(name); + if (v != nullptr && + !IsInstantiatedTSModule(v->AsImportEqualsVariable()->Declaration()->Node()-> + Parent()->AsTSImportEqualsDeclaration()->ModuleReference(), scope)) { + v = nullptr; + } + break; + } + default: + continue; + } + if (v != nullptr) { + findRes.push_back(v); + } + } +} + +bool Transformer::VerifyMemberExpressionDeque(binder::Variable *currVar, + ArenaDeque members) const +{ + ASSERT(!members.empty()); + switch (currVar->Flags()) { + case binder::VariableFlags::ENUM_LITERAL: { + // the recursion ends. + util::StringView enumMemberName = GetNameForMemberExpressionItem(members.front()); + members.pop_front(); + if (!members.empty()) { + return false; + } + binder::Variable *enumMemberVar = currVar->AsEnumLiteralVariable()->FindEnumMemberVariable(enumMemberName); + if (enumMemberVar == nullptr) { + return false; + } + if (!enumMemberVar->AsEnumVariable()->IsVisited()) { // visit the quoted item + auto *scope = enumMemberVar->AsEnumVariable()->Declaration()-> + Node()->Parent()->AsTSEnumDeclaration()->Scope(); + auto *initExpr = enumMemberVar->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init(); + if (IsStringInitForEnumMember(initExpr, scope)) { + enumMemberVar->AsEnumVariable()->SetStringInit(); + } + enumMemberVar->AsEnumVariable()->SetVisited(); + } + if (enumMemberVar->AsEnumVariable()->IsVisited() && enumMemberVar->AsEnumVariable()->StringInit()) { + return true; + } + + return false; + } + case binder::VariableFlags::NAMESPACE: { + auto *exportTSBindings = currVar->AsNamespaceVariable()->GetExportBindings(); + if (exportTSBindings != nullptr) { + ArenaVector findRes(Allocator()->Adapter()); + util::StringView name = GetNameForMemberExpressionItem(members.front()); + binder::Variable *v = exportTSBindings->FindExportTSVariable(name); + if (v != nullptr && IsInstantiatedNamespaceVariable(v)) { + findRes.push_back(v); + } + v = exportTSBindings->FindExportTSVariable(name); + if (v != nullptr) { + findRes.push_back(v); + } + v = exportTSBindings->FindExportTSVariable(name); + if (v != nullptr) { + findRes.push_back(v); + } + members.pop_front(); + + for (auto itemVar : findRes) { + if (VerifyMemberExpressionDeque(itemVar, members)) { + return true; + } + } + return false; + } + return false; + } + case binder::VariableFlags::IMPORT_EQUALS: { + // Replace import_equal + auto *node = currVar->Declaration()->Node()->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(); + while (node->IsTSQualifiedName()) { + members.push_front(node->AsTSQualifiedName()->Right()->AsIdentifier()); + node = node->AsTSQualifiedName()->Left(); + } + members.push_front(node->AsIdentifier()); + + ArenaVector findRes = FindFrontIdentifierTSVariables( + members.front()->AsIdentifier(), currVar->AsImportEqualsVariable()->GetScope()); + members.pop_front(); + + for (auto itemVar : findRes) { + if (VerifyMemberExpressionDeque(itemVar, members)) { + return true; + } + } + return false; + } + default: + return false; + } + + return false; +} + +util::StringView Transformer::GetNameForMemberExpressionItem(const ir::Expression *node) const +{ + util::StringView name {}; + if (node->IsIdentifier()) { + name = node->AsIdentifier()->Name(); + } else if (node->IsStringLiteral()) { + name = node->AsStringLiteral()->Str(); + } else if (node->IsTemplateLiteral()) { + name = node->AsTemplateLiteral()->Quasis().front()->Raw(); + } + return name; +} + +util::StringView Transformer::GetNameFromEnumMember(const ir::TSEnumMember *node) const +{ + util::StringView name {}; + if (node->Key()->IsIdentifier()) { + name = node->Key()->AsIdentifier()->Name(); + } else if (node->Key()->IsStringLiteral()) { + name = node->Key()->AsStringLiteral()->Str(); + } + return name; +} + +binder::Scope *Transformer::FindEnumMemberScope(const util::StringView name) const +{ + // Transform is required only if ident is an enumMember. + auto scope = Scope(); + while (scope != nullptr) { + if (scope->InLocalTSBindings(name)) { + return nullptr; + } + if (scope->IsTSModuleScope() && scope->AsTSModuleScope()->InExportBindings(name)) { + return nullptr; + } + if (scope->IsTSEnumScope() && scope->AsTSEnumScope()->FindEnumMemberVariable(name)) { + return scope; + } + if (scope->FindLocal(name)) { + return nullptr; + } + + if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { + scope = scope->Parent(); + } + scope = scope->Parent(); + } + + return nullptr; +} + +ir::MemberExpression *Transformer::CreateMemberExpressionFromIdentifier(binder::Scope *scope, ir::Identifier *node) +{ + auto identName = node->Name(); + auto moduleName = scope->IsTSEnumScope() ? FindTSEnumNameByScope(scope) : FindTSModuleNameByScope(scope); + auto *id = CreateReferenceIdentifier(moduleName); + auto *res = AllocNode(id, AllocNode(identName, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, + false, false); + SetOriginalNode(res, node); + return res; +} + } // namespace panda::es2panda::parser diff --git a/es2panda/parser/transformer/transformer.h b/es2panda/parser/transformer/transformer.h index 3ef64914db..3d109cdb75 100644 --- a/es2panda/parser/transformer/transformer.h +++ b/es2panda/parser/transformer/transformer.h @@ -32,6 +32,11 @@ struct TsModuleInfo { binder::Scope *scope; }; +struct TsEnumInfo { + util::StringView name; + binder::Scope *scope; +}; + using PrivatePropertyMap = std::unordered_map; using ComputedPropertyMap = std::unordered_map; @@ -66,6 +71,7 @@ public: explicit Transformer(panda::ArenaAllocator *allocator) : program_(nullptr), tsModuleList_(allocator->Adapter()), + tsEnumList_(allocator->Adapter()), classList_(allocator->Adapter()) { } @@ -136,20 +142,60 @@ private: util::StringView CreateUniqueName(const std::string &head, size_t *index = nullptr) const; util::StringView GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const; - util::StringView GetParamName(ir::TSModuleDeclaration *node, util::StringView name) const; + util::StringView GetParamName(ir::AstNode *node, util::StringView name) const; ir::Expression *GetClassMemberName(ir::Expression *key, bool isComputed, ir::Statement *node); binder::Scope *FindExportVariableInTsModuleScope(util::StringView name) const; binder::Variable *FindTSModuleVariable(const ir::Expression *node, binder::Scope *scope) const; util::StringView FindPrivatePropertyBindName(util::StringView name); void AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier); - bool IsInstantiatedTSModule(const ir::Expression *node) const; + bool IsInstantiatedTSModule(const ir::Expression *node, binder::Scope *scope) const; void SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const; + ir::UpdateNodes VisitTsEnumDeclaration(ir::TSEnumDeclaration *node, bool isExport = false); + ir::AstNode *CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name, ir::AstNode *node, bool isExport); + util::StringView GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration *node) const; + ir::CallExpression *CreateCallExpressionForTsEnum(ir::TSEnumDeclaration *node, util::StringView name, + bool isExport); + ir::ExpressionStatement *CreateTsEnumMember(ir::TSEnumMember *node, ir::TSEnumMember *preNode, + util::StringView enumLiteralName); + ir::ExpressionStatement *CreateTsEnumMemberWithStringInit(ir::TSEnumMember *node, + util::StringView enumLiteralName, + util::StringView enumMemberName); + ir::ExpressionStatement *CreateTsEnumMemberWithNumberInit(ir::TSEnumMember *node, + util::StringView enumLiteralName, + util::StringView enumMemberName); + ir::ExpressionStatement *CreateTsEnumMemberWithoutInit(ir::TSEnumMember *node, + ir::TSEnumMember *preNode, + util::StringView enumLiteralName, + util::StringView enumMemberName); + ArenaVector CreateCallExpressionArguments(util::StringView name, bool isExport); + bool IsStringInitForEnumMember(const ir::Expression *expr, binder::Scope *scope) const; + bool IsStringForMemberExpression(const ir::MemberExpression *memberExpr, binder::Scope *scope) const; + bool IsInstantiatedNamespaceVariable(binder::Variable *var) const; + ArenaVector FindFrontIdentifierTSVariables(const ir::Identifier *ident, + binder::Scope *scope) const; + void FindLocalTSVariables(binder::Scope *scope, const util::StringView name, + const std::vector &types, + ArenaVector &findRes) const; + void FindExportTSVariables(binder::Scope *scope, const util::StringView name, + const std::vector &types, + ArenaVector &findRes) const; + bool VerifyMemberExpressionDeque(binder::Variable *currVar, ArenaDeque members) const; + util::StringView GetNameForMemberExpressionItem(const ir::Expression *node) const; + util::StringView GetNameFromEnumMember(const ir::TSEnumMember *node) const; + binder::Scope *FindEnumMemberScope(const util::StringView name) const; + ir::MemberExpression *CreateMemberExpressionFromIdentifier(binder::Scope *scope, ir::Identifier *node); + bool IsTsModule() const { return (tsModuleList_.size() != 0); } + bool IsTsEnum() const + { + return (tsEnumList_.size() != 0); + } + template T *AllocNode(Args &&... args) { @@ -190,6 +236,16 @@ private: UNREACHABLE(); } + util::StringView FindTSEnumNameByScope(binder::Scope *scope) const + { + for (auto it : tsEnumList_) { + if (it.scope == scope) { + return it.name; + } + } + UNREACHABLE(); + } + ScriptExtension Extension() const { return program_->Extension(); @@ -235,6 +291,7 @@ private: Program *program_; ArenaVector tsModuleList_; + ArenaVector tsEnumList_; ArenaVector classList_; std::unordered_map tempVarDeclStatements_ {}; }; diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1-expected.txt new file mode 100644 index 0000000000..68b0d30d74 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1-expected.txt @@ -0,0 +1,14 @@ +0 +59 +33 +45 +1 +4 +7 +str_i +e +f +g +h +length +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1.ts new file mode 100644 index 0000000000..050ad0b6ac --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-1.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum tsEnum2 { + a, + b = 10 + 10 * 10 / 2 -1, + c = 3, + d = 1 << 5, + "e", + f = d + tsEnum2.c + 10, + g = 20 + 30 * 2 && 1, + h = "abcd".length, + length = h + "abc".length, + i = "str" + "_i" +} + +print(tsEnum2.a); +print(tsEnum2.b); +print(tsEnum2.e); +print(tsEnum2.f); +print(tsEnum2.g); +print(tsEnum2.h); +print(tsEnum2.length); +print(tsEnum2.i); + +print(tsEnum2[33]); +print(tsEnum2[45]); +print(tsEnum2[tsEnum2.g]); +print(tsEnum2["abcd".length]); +print(tsEnum2[7]); +print(tsEnum2["str_i"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10-expected.txt new file mode 100644 index 0000000000..00750edc07 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10-expected.txt @@ -0,0 +1 @@ +3 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10.ts new file mode 100644 index 0000000000..877e365470 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-10.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum E { + A = 1, + B = (() => {enum E {C = A + 1}; return E.C + 1})() +} +print(E.B); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11-expected.txt new file mode 100644 index 0000000000..371e502142 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11-expected.txt @@ -0,0 +1,5 @@ +1 +2 +6 +10 +B diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11.ts new file mode 100644 index 0000000000..a11ab4da1a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-11.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace E { + export enum E { + A = 0, + E = 1, + E_2 = 2, + B = (() => {enum E{ + C = A + 1, + E = 3, + E_1 = 5, + E_2 = E + 10, + E_3 = 1 && 2, + G = E_3 + 2 + } return E.C + 5;})(), + G = A + 10 + } +} + +print(E.E.E); +print(E.E.E_2); +print(E.E.B); +print(E.E.G); +print(E.E[6]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12-expected.txt new file mode 100644 index 0000000000..fdaed0a5b1 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12-expected.txt @@ -0,0 +1,7 @@ +0 +D +Str_B +Str_B +0 +Str_B +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12.ts new file mode 100644 index 0000000000..4a51a904ea --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-12.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum tsEnum1 { + A, + B="Str_B", + C=B, + D=A, + E=C +} + +print(tsEnum1.A); +print(tsEnum1[0]); +print(tsEnum1.B); +print(tsEnum1.C); +print(tsEnum1.D); +print(tsEnum1.E); +print(tsEnum1["Str_B"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13-expected.txt new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13-expected.txt @@ -0,0 +1 @@ +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13.ts new file mode 100644 index 0000000000..741f17853c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-13.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + export enum A { + C = 1, + B = 2 + } +} + +namespace ns { + export var a = A.B; +} + +print(ns.a); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14-expected.txt new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14-expected.txt @@ -0,0 +1 @@ +0 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14.ts new file mode 100644 index 0000000000..a40948d003 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-14.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace E { + export enum E { + A = 0, + E = 1, + E_2 = 2, + B = (() => {return A})() + } +} + +print(E.E.B); diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15-expected.txt new file mode 100644 index 0000000000..3e47f08990 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15-expected.txt @@ -0,0 +1,2 @@ +strstrstrstrstrstrstr +strstrstrstrstrstrstr diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15.ts new file mode 100644 index 0000000000..e093c57337 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-15.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + export enum E { + A = "str" + "str", + B = E.A, + C = B + E.A + ns.E.A + "str" + } +} + +enum E { + a = ns.E.C +} + +print(ns.E.C); +print(E.a); + diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16-expected.txt new file mode 100644 index 0000000000..31c1af47d3 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16-expected.txt @@ -0,0 +1,9 @@ +str +undefined +str +strstr +strstrstr +undefined +strstrstr +strstrstrstr +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16.ts new file mode 100644 index 0000000000..1657840fce --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-16.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum s1 { + a = "str", + b = "str" + "str" +} + +enum s2 { + a = "str", + c = a, +} + +enum s2_1 { + a = s1.a, + b = a+s2.a, + c = s2_1.b+"str" +} + +enum s3 { + a = ("str"), + b = (("str") + ("str"+"str")), + c = "str" + ("str") + s2_1.b +} + +print(s2.c); +print(s2["str"]); + +print(s2_1.a); +print(s2_1.b); +print(s2_1.c); +print(s2_1["strstrstr"]); + +print(s3.b); +print(s3.c); +print(s3["strstrstr"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17-expected.txt new file mode 100644 index 0000000000..9885a915a3 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17-expected.txt @@ -0,0 +1,3 @@ +1 +10 +11 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17.ts new file mode 100644 index 0000000000..9269f74cd5 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-17.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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. + */ + + +class A { + a= 1 +} + +function f1() +{ + return 10; +} + +var v = 11; + +enum E { + a = new A().a, + b = f1(), + c = 11 +} + +print(E.a); +print(E.b); +print(E.c); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18.ts new file mode 100644 index 0000000000..ef128788d2 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-18.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum ns { + a = "str" +} + +namespace ns2 { + namespace ns { + export var a = 1; + } + namespace ns { + enum A { + e = ns.a + } + print(A.e); + } +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19-expected.txt new file mode 100644 index 0000000000..3b99f1ac16 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19-expected.txt @@ -0,0 +1 @@ +str diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19.ts new file mode 100644 index 0000000000..83dbb31e8b --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-19.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + export enum A { + b = "str" + } +} + +namespace ns { + enum B { + b = A.b + } + print(B.b); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2-expected.txt new file mode 100644 index 0000000000..f4dbb4c56f --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2-expected.txt @@ -0,0 +1,11 @@ +0 +59 +33 +45 +1 +4 +str_i +e +f +h +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2.ts new file mode 100644 index 0000000000..bd15af7527 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-2.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum tsEnum3 { + a, + b = 10 + 10 * 10 / 2 -1, + c = 3, + d = 1 << 5, + "e" +} + +enum tsEnum3 { + f = d + tsEnum3.c + 10, + g = 20 + 30 * 2 && 1, + h = "abcd".length, + i = "str" + "_i" +} + +print(tsEnum3.a); +print(tsEnum3.b); +print(tsEnum3.e); +print(tsEnum3.f); +print(tsEnum3.g); +print(tsEnum3.h); +print(tsEnum3.i); + +print(tsEnum3[33]); +print(tsEnum3[45]); +print(tsEnum3[4]); +print(tsEnum3["str" + "_i"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20-expected.txt new file mode 100644 index 0000000000..eec9c130ef --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20-expected.txt @@ -0,0 +1,6 @@ +str +undefined +str +undefined +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20.ts new file mode 100644 index 0000000000..9baf4e99bc --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-20.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns2 { + export namespace ns1 { + export namespace ns1 { + export namespace ns { + export namespace ns{ + enum E {a = "str"} + enum E {b = a} + export enum E1 {a=E.b} + print(E1.a); + print(E1["str"]); + } + } + export enum E2 {a = ns.ns.E1.a} + print(E2.a); + print(E2["str"]); + } + } + enum E3 {a = ns2.ns1.ns1.E2.a} + print(E3.a); + print(E3["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21-expected.txt new file mode 100644 index 0000000000..eff632f100 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21-expected.txt @@ -0,0 +1,6 @@ +1 +c +2 +d +str +a diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21.ts new file mode 100644 index 0000000000..b68e47bf69 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-21.ts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + var ns = {E : {b : 1}}; + enum E1 { + c = ns.E.b, + d = {b:{c:2}}.b.c + } + print(E1.c); + print(E1[1]); + print(E1.d); + print(E1[2]); +} + +namespace ns { + export function f() : any { + return "str"; + } +} + +enum E { + a = ns.f() +} +print(E.a); +print(E[ns.f()]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22.ts new file mode 100644 index 0000000000..c126ddacea --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-22.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum A { + a = "str" +} + +namespace ns { + enum B { + b = A.a + } + print(B.b); + print(B["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23.ts new file mode 100644 index 0000000000..184dd32131 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-23.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns2 { + export enum A { + a = "str" + } +} + +enum E { + b = ns2.A["a"] +} + +print(E.b); +print(E["str"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24-expected.txt new file mode 100644 index 0000000000..d5d6878162 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24-expected.txt @@ -0,0 +1,2 @@ +3 +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24.ts new file mode 100644 index 0000000000..7d8a7f96aa --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-24.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace EE { + export enum a { + length = "str" + } +} +namespace ns3 { + enum EE { + a = "999" + } + export enum E3 { + a = EE.a.length + } +} + +print(ns3.E3.a); +print(ns3.E3["str"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25-expected.txt new file mode 100644 index 0000000000..1191247b6d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25.ts new file mode 100644 index 0000000000..972072e1c9 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-25.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum E4 { + a = 1, + b = (()=>{ + var a =2; + return a; + })() +} +print(E4.a); +print(E4.b); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26-expected.txt new file mode 100644 index 0000000000..ea15547ef7 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26-expected.txt @@ -0,0 +1,3 @@ +str +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26.ts new file mode 100644 index 0000000000..635e871bc9 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-26.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns101 { + export namespace ns102{ + export namespace ns103{ + export enum AAA{ + a="str" + } + export import eee=AAA; + } + export import ie5=ns103.AAA; + } + export import ie2=ns102.ns103; + export import ie3=ns101.ie2; + export import ie4=ns102.ns103.AAA; + +} + +import ie1 = ns101.ns102; + +enum E { + a=ie1.ns103.AAA.a, + b=ns101.ie2.eee.a, + c=ns101.ie3.AAA.a, + d=ns101.ie4.a, + e=ie1.ns103.eee.a, + f=ie1.ie5.a, + g=ns101.ns102.ie5.a +} + +print(E.a); +print(E.f); +print(E["str"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27-expected.txt new file mode 100644 index 0000000000..1a87c1e866 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27-expected.txt @@ -0,0 +1,3 @@ +undefined +undefined +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27.ts new file mode 100644 index 0000000000..5b5a6edc06 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-27.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + export enum E { + a=`123` + } +} + +enum E1 { + a=ns["E"].a +} + +enum E2 { + b=ns.E.a +} + +enum E3 { + c=ns[`E`].a +} + +print(E1["123"]); +print(E2["123"]); +print(E3["123"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28.ts new file mode 100644 index 0000000000..d0ceca08d5 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-28.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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. + */ + + +class ns{ + a = 1; +} +namespace ns { + export enum E { + a = "str", + } +} + +enum E2 { + a = ns.E.a +} +print(E2.a); +print(E2["str"]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29-expected.txt new file mode 100644 index 0000000000..f71b1fa46b --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29-expected.txt @@ -0,0 +1,3 @@ +1 +undefined +a diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29.ts new file mode 100644 index 0000000000..e12fed9792 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-29.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum ns { + a="Str" +} + +namespace ns1 { + var ns = {a:1}; + enum B { + a = ns.a + } + print(B.a); + print(B["Str"]); + print(B["1"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3-expected.txt new file mode 100644 index 0000000000..155507ccab --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3-expected.txt @@ -0,0 +1,2 @@ +3 +13 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3.ts new file mode 100644 index 0000000000..1cf99a55ec --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-3.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum tsEnum4 { + A, + B +} + +enum tsEnum4_1 { + A = tsEnum4.B + 2, + B = A + 10 +} + +print(tsEnum4_1.A); +print(tsEnum4_1.B); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30.ts new file mode 100644 index 0000000000..13e312e5a3 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-30.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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. + */ + + +class ns{ + a = 1; +} + +namespace ns { + export enum E { + a = "str", + } +} + +namespace ns2{ + enum E2 { + a = ns.E.a + } + print(E2.a); + print(E2["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31-expected.txt new file mode 100644 index 0000000000..2f1f45816b --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31-expected.txt @@ -0,0 +1,2 @@ +1 +b diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31.ts new file mode 100644 index 0000000000..8c59598702 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-31.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace a { + export enum toExponential { + length = "str", + } +} +enum E{ + a = 123, + b = a.toExponential.length, +} + +print(E.b); +print(E[E.a.toExponential.length]); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32.ts new file mode 100644 index 0000000000..384ab055cf --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-32.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + + export enum E1 { + a = "str" + } + + enum E { + A = ns.E1.a + } + + namespace ns2 { + namespace ns { + var b = 1; + } + } + print(E.A); + print(E["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33-expected.txt new file mode 100644 index 0000000000..0dcadea512 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33-expected.txt @@ -0,0 +1,3 @@ +str +undefined +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33.ts new file mode 100644 index 0000000000..bd2412516e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-33.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f() { + enum E { + a = ns1.E1.a, + b = ns2.E2.b, + c = ns1.E1.a + ns2.E2.b, + } + print(E.a); + print(E["str"]); + print(E["strstr"]); +} + +namespace ns1 { + export enum E1{ + a="str", + } +} + +namespace ns2 { + export enum E2 { + a = "str", + c = a, + b = c + } +} + +f(); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34.ts new file mode 100644 index 0000000000..b911a1b5d0 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-34.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum ns{ + a = "str" +} +namespace ns{ + namespace ns{} + enum E{ + a = ns.a, + } + print(E.a); + print(E["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35-expected.txt new file mode 100644 index 0000000000..819def9331 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35-expected.txt @@ -0,0 +1,2 @@ +str +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35.ts new file mode 100644 index 0000000000..d76751d756 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-35.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +enum ns{ + a = "str" +} +namespace ns{ + namespace ns1{} + import ns = ns1 + enum E{ + a = ns.a, + } + print(E.a); + print(E["str"]); +} \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4-expected.txt new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4-expected.txt @@ -0,0 +1 @@ +5 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4.ts new file mode 100644 index 0000000000..f146ff4bc6 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-4.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns1 { + export enum tsEnum1 { + A, + B = 2 + } +} + +namespace ns1 { + export enum tsEnum1 { + C = B + 3, + D + } +} + +print(ns1.tsEnum1.C); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5-expected.txt new file mode 100644 index 0000000000..b4de394767 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5-expected.txt @@ -0,0 +1 @@ +11 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5.ts new file mode 100644 index 0000000000..a6cc58f6ff --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-5.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace tsEnum5 { + export enum tsEnum5 { + A, + B = 10 + } +} +enum tsEnum5 { + B = tsEnum5.tsEnum5.B + 1 +} + +print(tsEnum5.B); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6-expected.txt new file mode 100644 index 0000000000..48647efc33 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6-expected.txt @@ -0,0 +1,2 @@ +str_C +undefined diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6.ts new file mode 100644 index 0000000000..788e57f674 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-6.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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. + */ + + +function f1() { + enum tsEnum6 { + A = "str_A", + B = "str_" + "B", + C = "str" + "_" +"C" + } + print(tsEnum6.C); + print(tsEnum6["str_A"]); +} + +f1(); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7-expected.txt new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7-expected.txt @@ -0,0 +1 @@ +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7.ts new file mode 100644 index 0000000000..a0019c7790 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-7.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace nsm1 { + export enum tsEnum7 { + A, + B + } +} + +module nsm1 { + export enum tsEnum7 { + C = B + 1 + } +} + +print(nsm1.tsEnum7.C); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8-expected.txt new file mode 100644 index 0000000000..b4de394767 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8-expected.txt @@ -0,0 +1 @@ +11 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8.ts new file mode 100644 index 0000000000..8a5646257e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-8.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns9 { + export enum tsEnum9 { + A, + B + } + export enum tsEnum9 { + C = 10, + D = B + C + } +} + +print(ns9.tsEnum9.D); \ No newline at end of file diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9-expected.txt b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9-expected.txt new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9-expected.txt @@ -0,0 +1 @@ +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9.ts b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9.ts new file mode 100644 index 0000000000..511ad96be6 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/enums/test-ts-enum-9.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + + +namespace ns { + var v = 1; +} + +enum ns { + a, + b, + v +} + +module ns { + var v = 2; +} + +print(ns.v); \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-enum-declaration1-expected.txt b/es2panda/test/parser/ts/test-enum-declaration1-expected.txt index 1401555d35..7ad4b9386e 100644 --- a/es2panda/test/parser/ts/test-enum-declaration1-expected.txt +++ b/es2panda/test/parser/ts/test-enum-declaration1-expected.txt @@ -1,116 +1 @@ -{ - "type": "Program", - "statements": [ - { - "type": "TSEnumDeclaration", - "id": { - "type": "Identifier", - "name": "foo", - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 6 - }, - "end": { - "line": 17, - "column": 9 - } - } - }, - "members": [ - { - "type": "TSEnumMember", - "id": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 18, - "column": 5 - }, - "end": { - "line": 18, - "column": 6 - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 6 - }, - "end": { - "line": 18, - "column": 7 - } - } - }, - { - "type": "TSEnumMember", - "id": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 19, - "column": 5 - }, - "end": { - "line": 19, - "column": 6 - } - } - }, - "initializer": { - "type": "StringLiteral", - "value": "bar", - "loc": { - "start": { - "line": 19, - "column": 9 - }, - "end": { - "line": 19, - "column": 14 - } - } - }, - "loc": { - "start": { - "line": 19, - "column": 9 - }, - "end": { - "line": 19, - "column": 15 - } - } - } - ], - "const": false, - "loc": { - "start": { - "line": 17, - "column": 1 - }, - "end": { - "line": 20, - "column": 2 - } - } - } - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 21, - "column": 1 - } - } -} +SyntaxError: Variable 'a' has already been declared. [test-enum-declaration1.ts:19:5] -- Gitee From c7a7dd119adfbd036cf3d26b2c9391c8fab4681a Mon Sep 17 00:00:00 2001 From: zengyuan Date: Mon, 24 Oct 2022 16:24:27 +0800 Subject: [PATCH 38/59] Fix bug of multiple rest elements in tuple Description: Support to report the error when a rest element follows another rest element in tuple. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5XJCX Signed-off-by: zengyuan Change-Id: Ic3ca4c4ac049385d5e6d278b8d07c14f809b7f0b --- es2panda/parser/parserImpl.cpp | 18 ++++++++++++++++-- es2panda/parser/parserImpl.h | 3 ++- .../parser/ts/test-tuple-type10-expected.txt | 1 + es2panda/test/parser/ts/test-tuple-type10.ts | 18 ++++++++++++++++++ .../parser/ts/test-tuple-type7-expected.txt | 1 + es2panda/test/parser/ts/test-tuple-type7.ts | 17 +++++++++++++++++ .../parser/ts/test-tuple-type8-expected.txt | 1 + es2panda/test/parser/ts/test-tuple-type8.ts | 17 +++++++++++++++++ .../parser/ts/test-tuple-type9-expected.txt | 1 + es2panda/test/parser/ts/test-tuple-type9.ts | 18 ++++++++++++++++++ 10 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 es2panda/test/parser/ts/test-tuple-type10-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type10.ts create mode 100644 es2panda/test/parser/ts/test-tuple-type7-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type7.ts create mode 100644 es2panda/test/parser/ts/test-tuple-type8-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type8.ts create mode 100644 es2panda/test/parser/ts/test-tuple-type9-expected.txt create mode 100644 es2panda/test/parser/ts/test-tuple-type9.ts diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index c1af0bba70..343841808c 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -804,7 +804,15 @@ bool ParserImpl::IsTSNamedTupleMember() return isNamedMember; } -ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional) +void ParserImpl::HandleRestType(ir::AstNodeType elementType, bool *hasRestType) +{ + if (elementType == ir::AstNodeType::TS_ARRAY_TYPE && *hasRestType) { + ThrowSyntaxError("A rest element cannot follow another rest element"); + } + *hasRestType = true; +} + +ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional, bool *hasRestType) { lexer::SourcePosition startPos = lexer_->GetToken().Start(); ir::Expression *element = nullptr; @@ -843,6 +851,10 @@ ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *see auto *elementType = ParseTsTypeAnnotation(&options); ASSERT(elementType != nullptr); + if (elementType && isRestType) { + HandleRestType(elementType->Type(), hasRestType); + } + element = AllocNode(elementIdent, elementType, isOptional, isRestType); element->SetRange({startPos, elementType->End()}); } else { @@ -854,6 +866,7 @@ ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *see element = ParseTsTypeAnnotation(&options); ASSERT(element != nullptr); if (element && isRestType) { + HandleRestType(element->Type(), hasRestType); lexer::SourcePosition endPos = element->End(); element = AllocNode(std::move(element)); element->SetRange({startPos, endPos}); @@ -880,11 +893,12 @@ ir::TSTupleType *ParserImpl::ParseTsTupleType() ArenaVector elements(Allocator()->Adapter()); ir::TSTupleKind kind = ir::TSTupleKind::NONE; bool seenOptional = false; + bool hasRestType = false; lexer_->NextToken(); // eat '[' while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { - ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional); + ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional, &hasRestType); elements.push_back(element); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index fc1663e5e9..aabaef7188 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -260,7 +260,8 @@ private: ir::Expression *ParseTsQualifiedReference(ir::Expression *typeName); ir::Expression *ParseTsTypeReferenceOrQuery(bool parseQuery = false); bool IsTSNamedTupleMember(); - ir::Expression *ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional); + void HandleRestType(ir::AstNodeType elementType, bool *hasRestType); + ir::Expression *ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional, bool *hasRestType); ir::TSTupleType *ParseTsTupleType(); ir::TSImportType *ParseTsImportType(const lexer::SourcePosition &startLoc, bool isTypeof = false); ir::Expression *ParseTsTypeAnnotation(TypeAnnotationParsingOptions *options); diff --git a/es2panda/test/parser/ts/test-tuple-type10-expected.txt b/es2panda/test/parser/ts/test-tuple-type10-expected.txt new file mode 100644 index 0000000000..ba4c86b6c8 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type10-expected.txt @@ -0,0 +1 @@ +SyntaxError: A rest element cannot follow another rest element [test-tuple-type10.ts:18:64] diff --git a/es2panda/test/parser/ts/test-tuple-type10.ts b/es2panda/test/parser/ts/test-tuple-type10.ts new file mode 100644 index 0000000000..938edf58d0 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type10.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +type STRINGS = string[] +type WithMutipleRest4 = [...first: STRINGS, ...second: string[]]; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-tuple-type7-expected.txt b/es2panda/test/parser/ts/test-tuple-type7-expected.txt new file mode 100644 index 0000000000..01ff5953ca --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type7-expected.txt @@ -0,0 +1 @@ +SyntaxError: A rest element cannot follow another rest element [test-tuple-type7.ts:17:78] diff --git a/es2panda/test/parser/ts/test-tuple-type7.ts b/es2panda/test/parser/ts/test-tuple-type7.ts new file mode 100644 index 0000000000..33417a6b9d --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type7.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +type WithMutipleRest = [first: number, ...rest1: string[], ...rest2: string[]]; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-tuple-type8-expected.txt b/es2panda/test/parser/ts/test-tuple-type8-expected.txt new file mode 100644 index 0000000000..4d9d3bfe29 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type8-expected.txt @@ -0,0 +1 @@ +SyntaxError: A rest element cannot follow another rest element [test-tuple-type8.ts:17:50] diff --git a/es2panda/test/parser/ts/test-tuple-type8.ts b/es2panda/test/parser/ts/test-tuple-type8.ts new file mode 100644 index 0000000000..1d2c7bd83c --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type8.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +type WithMutipleRest2 = [...number[], ...string[]]; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-tuple-type9-expected.txt b/es2panda/test/parser/ts/test-tuple-type9-expected.txt new file mode 100644 index 0000000000..2b1decffb7 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type9-expected.txt @@ -0,0 +1 @@ +SyntaxError: A rest element cannot follow another rest element [test-tuple-type9.ts:18:52] diff --git a/es2panda/test/parser/ts/test-tuple-type9.ts b/es2panda/test/parser/ts/test-tuple-type9.ts new file mode 100644 index 0000000000..435b8ef0c4 --- /dev/null +++ b/es2panda/test/parser/ts/test-tuple-type9.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 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. + */ + + +type NUMBERSARR = number[] +type WithMutipleRest3 = [...NUMBERSARR, ...string[]]; \ No newline at end of file -- Gitee From bc4061cc913cac665e8abe26cfe4c804affd122e Mon Sep 17 00:00:00 2001 From: qiuyu Date: Tue, 8 Nov 2022 16:59:28 +0800 Subject: [PATCH 39/59] Bugfix for ScopeInsIndex Bugfix for ScopeInsIndex Issue: #I603TB Signed-off-by: qiuyu Change-Id: Ibe528ee77ea9f816b6b14daee5eb5a954ad277a0 --- ts2panda/src/debuginfo.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index b49a58105a..7e95232598 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -309,13 +309,17 @@ export class DebugInfo { ( insns[i]).getScope().setScopeStartInsIdx(i); // delete ins placeholder insns.splice(i, 1); - i--; + if (i > 0) { + i--; + } } if (insns[i] instanceof DebugInsEndPlaceHolder) { - ( insns[i]).getScope().setScopeEndInsIdx(i); + ( insns[i]).getScope().setScopeEndInsIdx(i > 0 ? i - 1 : 0); // delete ins placeholder insns.splice(i, 1); - i--; + if (i > 0) { + i--; + } } } -- Gitee From ce999e4828a6ec2291b2d01c6a8d268f225a681d Mon Sep 17 00:00:00 2001 From: jing_han Date: Wed, 9 Nov 2022 09:27:54 +0800 Subject: [PATCH 40/59] Add a coverage script Signed-off-by: jing_han issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5XWEN --- test262/copy_gcda.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ test262/llvm_gcov.sh | 19 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 test262/copy_gcda.sh create mode 100644 test262/llvm_gcov.sh diff --git a/test262/copy_gcda.sh b/test262/copy_gcda.sh new file mode 100644 index 0000000000..bead95b55a --- /dev/null +++ b/test262/copy_gcda.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (c) 2021-2022 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. +SCRIPT_DIR=$(cd $(dirname $0);pwd) + +if [ $# -eq 0 ]; +then + GCDA_PATH=${SCRIPT_DIR%/*} + GCDA_PATH=${GCDA_PATH%/*} + GCDA_PATH=${GCDA_PATH%/*} + GCDA_FILE_PATH="/out/" + FINAL_GCDA_PATH=$GCDA_PATH$GCDA_FILE_PATH + ETS_FRONTEND=${SCRIPT_DIR%/*} + TEXT_NAME="/out/lcov_all" + TEXT_NAME_DIR=$ETS_FRONTEND$TEXT_NAME + mkdir -p $TEXT_NAME_DIR + TEXT_NAME=$TEXT_NAME_DIR/file_name.txt + find $FINAL_GCDA_PATH -name '*.gcda' > $TEXT_NAME + find $FINAL_GCDA_PATH -name '*.gcno' >> $TEXT_NAME + for line in $(cat $TEXT_NAME) + do + gcda_file_dir="" + gcda_file_dir=${line#*'out/'} + gcda_file_dir=$TEXT_NAME_DIR/gcda_file/$gcda_file_dir + gcda_file_dir=${gcda_file_dir%/*} + mkdir -p $gcda_file_dir + cp -rf $line $gcda_file_dir + done + # find $FINAL_GCDA_PATH -name '*.gcda' | xargs rm -rf + chmod +x $SCRIPT_DIR/llvm_gcov.sh + lcov -d $TEXT_NAME_DIR -o $TEXT_NAME_DIR/cov_oa_all.info -c --gcov-tool $SCRIPT_DIR/llvm_gcov.sh +fi \ No newline at end of file diff --git a/test262/llvm_gcov.sh b/test262/llvm_gcov.sh new file mode 100644 index 0000000000..5e956e8ff7 --- /dev/null +++ b/test262/llvm_gcov.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env sh +# Copyright (c) 2021-2022 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. + +SCRIPT_DIR=$(cd $(dirname $0);pwd) +PREBUILTS=prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-cov +DIR=${SCRIPT_DIR%'arkcompiler'*} +DIR=$DIR$PREBUILTS +exec $DIR gcov "$@" \ No newline at end of file -- Gitee From dcd4c0f49b086a704a3252f5facc918326a2c1fa Mon Sep 17 00:00:00 2001 From: hufeng Date: Tue, 1 Nov 2022 21:25:32 +0800 Subject: [PATCH 41/59] Fix no restoring before CFG on ES2ABC Signed-off-by: hufeng Change-Id: Ia668f7977628c6b6689506b468cff6a7764fbd5e --- es2panda/compiler/core/function.cpp | 1 + es2panda/compiler/core/pandagen.cpp | 198 ++++++------- es2panda/compiler/core/pandagen.h | 18 +- es2panda/compiler/core/regAllocator.cpp | 215 +++++++------- es2panda/compiler/core/regAllocator.h | 152 ++++------ es2panda/compiler/templates/isa.h.erb | 40 ++- es2panda/ir/irnode.h | 10 + .../test-spill-fill-with-CFG-expected.txt | 1 + .../regAllocator/test-spill-fill-with-CFG.js | 274 ++++++++++++++++++ 9 files changed, 608 insertions(+), 301 deletions(-) create mode 100644 es2panda/test/compiler/js/regAllocator/test-spill-fill-with-CFG-expected.txt create mode 100644 es2panda/test/compiler/js/regAllocator/test-spill-fill-with-CFG.js diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index 9143ac1ca2..3769926906 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -205,6 +205,7 @@ static void CompileFunctionOrProgram(PandaGen *pg) void Function::Compile(PandaGen *pg) { CompileFunctionOrProgram(pg); + pg->AdjustSpillInsns(); pg->SetFunctionKind(); pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION); pg->CopyFunctionArguments(pg->RootNode()); diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index ed81f39bda..a7c61bf5f4 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -91,7 +91,7 @@ void PandaGen::SetFunctionKind() Label *PandaGen::AllocLabel() { std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++); - return sa_.AllocLabel(std::move(id)); + return ra_.AllocLabel(std::move(id)); } bool PandaGen::IsDebug() const @@ -210,6 +210,8 @@ void PandaGen::InitializeLexEnv(const ir::AstNode *node) void PandaGen::CopyFunctionArguments(const ir::AstNode *node) { FrontAllocator fa(this); + auto spillRegsCount = ra_.GetSpillRegsCount(); + totalRegs_ += spillRegsCount; VReg targetReg = totalRegs_; for (const auto *param : topScope_->ParamScope()->Params()) { @@ -221,11 +223,11 @@ void PandaGen::CopyFunctionArguments(const ir::AstNode *node) auto typeIndex = context_->TypeRecorder()->GetVariableTypeIndex(param); if (typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { // Simply encode type index for params - MoveVregWithType(node, -(typeIndex + 1), param->Vreg(), targetReg++); + MoveVregWithType(node, -(typeIndex + 1), param->Vreg() + spillRegsCount, targetReg++); continue; } } - MoveVreg(node, param->Vreg(), targetReg++); + MoveVreg(node, param->Vreg() + spillRegsCount, targetReg++); } } @@ -462,9 +464,9 @@ void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringVi } else { int64_t typeIndex = extractor::TypeExtractor::GetBuiltinTypeIndex(name); if (context_->IsTypeExtractorEnabled() && typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { - sa_.EmitWithType(node, typeIndex, 0, name); + ra_.EmitWithType(node, typeIndex, 0, name); } else { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); } } strings_.insert(name); @@ -493,7 +495,7 @@ void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringV if (isDebuggerEvaluateExpressionMode()) { StoreObjByNameViaDebugger(node, name); } else { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); } strings_.insert(name); } @@ -501,7 +503,7 @@ void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringV void PandaGen::LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) { LoadAccumulator(node, obj); // object is load to acc - sa_.Emit(node, 0, prop); + ra_.Emit(node, 0, prop); strings_.insert(prop); } @@ -515,11 +517,11 @@ void PandaGen::LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) { LoadAccumulator(node, obj); // object is load to acc if (index <= util::Helpers::MAX_INT16) { - sa_.Emit(node, 0, index); + ra_.Emit(node, 0, index); return; } - sa_.Emit(node, index); + ra_.Emit(node, index); } void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj) @@ -586,13 +588,13 @@ void PandaGen::LoadAccumulator(const ir::AstNode *node, VReg reg) void PandaGen::LoadGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } @@ -608,28 +610,28 @@ void PandaGen::StoreAccToLexEnv(const ir::AstNode *node, const binder::ScopeFind void PandaGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str) { - sa_.Emit(node, str); + ra_.Emit(node, str); strings_.insert(str); } void PandaGen::LoadAccumulatorFloat(const ir::AstNode *node, double num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, int32_t num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num) { - sa_.Emit(node, static_cast(num)); + ra_.Emit(node, static_cast(num)); } void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num) { - sa_.Emit(node, num); + ra_.Emit(node, num); strings_.insert(num); } @@ -643,39 +645,39 @@ void PandaGen::LoadConst(const ir::AstNode *node, Constant id) { switch (id) { case Constant::JS_HOLE: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_NAN: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_INFINITY: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_GLOBAL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_UNDEFINED: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_SYMBOL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_NULL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_TRUE: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_FALSE: { - sa_.Emit(node); + ra_.Emit(node); break; } default: { @@ -696,12 +698,12 @@ void PandaGen::MoveVregWithType(const ir::AstNode *node, int64_t typeIndex, VReg void PandaGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label) { - sa_.AddLabel(label); + ra_.AddLabel(label); } void PandaGen::Branch(const ir::AstNode *node, Label *label) { - sa_.Emit(node, label); + ra_.Emit(node, label); } bool PandaGen::CheckControlFlowChange() const @@ -831,12 +833,12 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) } case lexer::TokenType::PUNCTUATOR_MINUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_TILDE: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { @@ -845,12 +847,12 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) } case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::KEYW_VOID: @@ -1020,7 +1022,7 @@ void PandaGen::GreaterEqual(const ir::AstNode *node, VReg lhs) void PandaGen::IsTrue(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) @@ -1030,7 +1032,7 @@ void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); Equal(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) @@ -1040,7 +1042,7 @@ void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); Equal(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target) @@ -1050,13 +1052,13 @@ void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label * StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); StrictEqual(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target) { IsTrue(node); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) @@ -1067,8 +1069,8 @@ void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) { - sa_.Emit(node); - sa_.Emit(node, target); + ra_.Emit(node); + ra_.Emit(node, target); } void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target) @@ -1078,12 +1080,12 @@ void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target) StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_NULL); ra_.Emit(node, 0, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::EmitThrow(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::EmitRethrow(const ir::AstNode *node) @@ -1100,7 +1102,7 @@ void PandaGen::EmitRethrow(const ir::AstNode *node) LoadAccumulator(node, exception); NotEqual(node, hole); - sa_.Emit(node, skipThrow); + ra_.Emit(node, skipThrow); SetLabel(node, doThrow); LoadAccumulator(node, exception); @@ -1111,12 +1113,12 @@ void PandaGen::EmitRethrow(const ir::AstNode *node) void PandaGen::EmitReturn(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::EmitReturnUndefined(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::ImplicitReturn(const ir::AstNode *node) @@ -1190,11 +1192,11 @@ void PandaGen::CallThis(const ir::AstNode *node, VReg startReg, size_t argCount) default: { int64_t actualArgs = argCount - 1; if (actualArgs <= util::Helpers::MAX_INT8) { - rra_.Emit(node, thisReg, argCount, 0, actualArgs, thisReg); + ra_.EmitRange(node, argCount, 0, actualArgs, thisReg); break; } - rra_.Emit(node, thisReg, argCount, actualArgs, thisReg); + ra_.EmitRange(node, argCount, actualArgs, thisReg); break; } } @@ -1205,7 +1207,7 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) LoadAccumulator(node, startReg); // callee is load to acc switch (argCount) { case 0: { // 0 args - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case 1: { // 1 arg @@ -1229,11 +1231,11 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) default: { VReg arg0 = startReg + 1; if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, arg0, argCount, 0, argCount, arg0); + ra_.EmitRange(node, argCount, 0, argCount, arg0); break; } - rra_.Emit(node, arg0, argCount, argCount, arg0); + ra_.EmitRange(node, argCount, argCount, arg0); break; } } @@ -1244,20 +1246,20 @@ void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount if (RootNode()->AsScriptFunction()->IsArrow()) { GetFunctionObject(node); // load funcobj to acc for super call in arrow function if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); } else { - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } return; } if (argCount <= util::Helpers::MAX_INT8) { // no need to load funcobj to acc for super call in other kinds of functions - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); return; } - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs) @@ -1268,11 +1270,11 @@ void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs) void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount) { if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); return; } - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) @@ -1293,7 +1295,7 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction void PandaGen::TypeOf(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args) @@ -1309,7 +1311,7 @@ void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj) void PandaGen::GetUnmappedArgs(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::Negate(const ir::AstNode *node) @@ -1327,13 +1329,13 @@ void PandaGen::Negate(const ir::AstNode *node) void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) { LoadAccumulator(node, arg); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::ToNumeric(const ir::AstNode *node, VReg arg) { LoadAccumulator(node, arg); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) @@ -1383,18 +1385,18 @@ void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj) void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj) { LoadAccumulator(node, genObj); - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj) { LoadAccumulator(node, genObj); - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) @@ -1425,17 +1427,17 @@ void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj) void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value) { LoadAccumulator(node, value); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index) { - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : ra_.Emit(node, index); } void PandaGen::GetPropIterator(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter) @@ -1445,7 +1447,7 @@ void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter) void PandaGen::CreateEmptyObject(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx) @@ -1453,7 +1455,7 @@ void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx) ASSERT(util::Helpers::IsInteger(idx)); std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx); util::UString litId(idxStr, allocator_); - sa_.Emit(node, 0, litId.View()); + ra_.Emit(node, 0, litId.View()); } void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj) @@ -1476,7 +1478,7 @@ void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg void PandaGen::CreateEmptyArray(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx) @@ -1484,7 +1486,7 @@ void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx) ASSERT(util::Helpers::IsInteger(idx)); std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx); util::UString litId(idxStr, allocator_); - sa_.Emit(node, 0, litId.View()); + ra_.Emit(node, 0, litId.View()); } void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector &elements, VReg obj) @@ -1595,19 +1597,19 @@ void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetIterator(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::GetAsyncIterator(const ir::AstNode *node) { /* * TODO: async iterator - * sa_.Emit(node); + * ra_.Emit(node); */ } @@ -1622,18 +1624,16 @@ void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, V size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1); if (argRegCnt <= util::Helpers::MAX_INT8) { - rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), - obj, argStart); + ra_.EmitRange(node, argCount, static_cast(argRegCnt), obj, argStart); return; } - rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), - obj, argStart); + ra_.EmitRange(node, argCount, static_cast(argRegCnt), obj, argStart); } void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter) @@ -1653,28 +1653,28 @@ void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::String void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::GetModuleNamespace(const ir::AstNode *node, uint32_t index) { - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::DynamicImportCall(const ir::AstNode *node) @@ -1691,7 +1691,7 @@ void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::Stri void PandaGen::LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key) { LoadAccumulator(node, obj); // object is load to acc - sa_.Emit(node, 0, key); + ra_.Emit(node, 0, key); strings_.insert(key); } @@ -1751,27 +1751,27 @@ void PandaGen::LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operan void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); return; } - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); } void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name) { if (context_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(name)); - sa_.Emit(node, patchSlot); + ra_.Emit(node, patchSlot); return; } if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); return; } - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); } void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) @@ -1799,7 +1799,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t { if (context_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(name)); - sa_.Emit(node, patchSlot); + ra_.Emit(node, patchSlot); return; } RegScope rs(this); @@ -1810,7 +1810,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name) @@ -1838,14 +1838,14 @@ void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringV void PandaGen::PopLexEnv(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CopyLexEnv(const ir::AstNode *node) { /* * TODO: add copy lexenv to optimize the loop env creation - * sa_.Emit(node); + * ra_.Emit(node); */ } @@ -1862,15 +1862,15 @@ void PandaGen::NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::Vari void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num) { - num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num) : sa_.Emit(node, num); + num <= util::Helpers::MAX_INT8 ? ra_.Emit(node, num) : ra_.Emit(node, num); } void PandaGen::NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx) { std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(scopeInfoIdx); util::UString litId(idxStr, allocator_); - num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num, litId.View()) : - sa_.Emit(node, num, litId.View()); + num <= util::Helpers::MAX_INT8 ? ra_.Emit(node, num, litId.View()) : + ra_.Emit(node, num, litId.View()); } uint32_t PandaGen::TryDepth() const @@ -1990,13 +1990,13 @@ VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed) void PandaGen::StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 02f17f126c..4e85174c87 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -89,9 +89,7 @@ public: catchList_(allocator_->Adapter()), strings_(allocator_->Adapter()), buffStorage_(allocator_->Adapter()), - sa_(this), - ra_(this), - rra_(this) + ra_(this) { } ~PandaGen() = default; @@ -143,6 +141,11 @@ public: return insns_; } + void SetInsns(ArenaList newInsns) + { + insns_ = newInsns; + } + ArenaMap &TypedInsns() { return typedInsns_; @@ -205,9 +208,12 @@ public: void SetSourceLocationFlag(lexer::SourceLocationFlag flag) { - sa_.SetSourceLocationFlag(flag); ra_.SetSourceLocationFlag(flag); - rra_.SetSourceLocationFlag(flag); + } + + void AdjustSpillInsns() + { + ra_.AdjustInsRegWhenHasSpill(); } panda::panda_file::FunctionKind GetFunctionKind() const @@ -480,9 +486,7 @@ private: DynamicContext *dynamicContext_ {}; OptionalChain *optionalChain_ {}; InlineCache ic_; - SimpleAllocator sa_; RegAllocator ra_; - RangeRegAllocator rra_; IcSizeType currentSlot_ {0}; uint32_t usedRegs_ {0}; diff --git a/es2panda/compiler/core/regAllocator.cpp b/es2panda/compiler/core/regAllocator.cpp index 88613e85bd..79410e310c 100644 --- a/es2panda/compiler/core/regAllocator.cpp +++ b/es2panda/compiler/core/regAllocator.cpp @@ -21,168 +21,187 @@ namespace panda::es2panda::compiler { -// AllocatorBase +// FrontAllocator -void AllocatorBase::PushBack(IRNode *ins) +FrontAllocator::FrontAllocator(PandaGen *pg) + : pg_(pg), insn_(std::move(pg_->Insns()), pg_->Allocator()->Adapter()) { - pg_->Insns().push_back(ins); } -ArenaAllocator *AllocatorBase::Allocator() const +FrontAllocator::~FrontAllocator() { - return pg_->Allocator(); + pg_->Insns().splice(pg_->Insns().end(), std::move(insn_)); } -void AllocatorBase::UpdateIcSlot(IRNode *node) +// RegAllocator + +void RegAllocator::PushBack(IRNode *ins) { - auto inc = node->SetIcSlot(pg_->GetCurrentSlot()); - pg_->IncreaseCurrentSlot(inc); + pg_->Insns().push_back(ins); } -void SimpleAllocator::Run(IRNode *ins, int64_t typeIndex) +ArenaAllocator *RegAllocator::Allocator() const { - PushBack(ins); - pg_->TypedInsns()[ins] = typeIndex; + return pg_->Allocator(); } -// FrontAllocator - -FrontAllocator::FrontAllocator(PandaGen *pg) - : AllocatorBase(pg), insn_(std::move(pg_->Insns()), pg_->Allocator()->Adapter()) +uint16_t RegAllocator::GetSpillRegsCount() const { + return spillRegs_; } -FrontAllocator::~FrontAllocator() +void RegAllocator::UpdateIcSlot(IRNode *node) { - pg_->Insns().splice(pg_->Insns().end(), std::move(insn_)); + auto inc = node->SetIcSlot(pg_->GetCurrentSlot()); + pg_->IncreaseCurrentSlot(inc); } -// SimpleAllocator -Label *SimpleAllocator::AllocLabel(std::string &&id) +Label *RegAllocator::AllocLabel(std::string &&id) { const auto *lastInsNode = pg_->Insns().empty() ? FIRST_NODE_OF_FUNCTION : pg_->Insns().back()->Node(); return Alloc