From f649392b558d6d5f25139c5ba6099b2c3457f15f Mon Sep 17 00:00:00 2001 From: songqi Date: Thu, 22 Sep 2022 10:05:16 +0800 Subject: [PATCH] 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