diff --git a/CMakeLists.txt b/CMakeLists.txt index e49880048b39a7862c1959de208a79d92c2719a7..a1096c244a92d1a48fae11feef594a40ca4cfc16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,6 +242,7 @@ set(ES2PANDA_LIB_SRC ir/ets/etsTypeReferencePart.cpp ir/ets/etsWildcardType.cpp ir/ets/etsImportSource.cpp + ir/ets/etsNamespaceDeclaration.cpp ir/ts/tsAnyKeyword.cpp ir/ts/tsArrayType.cpp ir/ts/tsAsExpression.cpp diff --git a/checker/ETSAnalyzer.cpp b/checker/ETSAnalyzer.cpp index 2e05e528f30d1b428c49aef664379507c47a488b..a4624562b656485d72fa5dc285fbbce12257cc84 100644 --- a/checker/ETSAnalyzer.cpp +++ b/checker/ETSAnalyzer.cpp @@ -40,6 +40,11 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::NamedType *node) const UNREACHABLE(); } +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::etsNamespaceDeclaration *node) const +{ + UNREACHABLE(); +} + checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::PrefixAssertionExpression *expr) const { UNREACHABLE(); diff --git a/checker/TSAnalyzer.cpp b/checker/TSAnalyzer.cpp index f5bfa79b2f493c500b2a5eb57e720362351182ea..c4142034087c6d3d558dcd9f5cc9eeb0272340b8 100644 --- a/checker/TSAnalyzer.cpp +++ b/checker/TSAnalyzer.cpp @@ -31,6 +31,11 @@ TSChecker *TSAnalyzer::GetTSChecker() const return static_cast(GetChecker()); } +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::etsNamespaceDeclaration *node) const +{ + UNREACHABLE(); +} + // from as folder checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::NamedType *node) const { diff --git a/checker/ets/enum.cpp b/checker/ets/enum.cpp index d785b17cca0131fabf59cc537bb0b431864b0806..3995327059a93aecc818a8779d503cfc93196191 100644 --- a/checker/ets/enum.cpp +++ b/checker/ets/enum.cpp @@ -137,18 +137,25 @@ template binder::FunctionParamScope *const param_scope, ArenaVector &¶ms, ArenaVector &&body, - ir::TypeNode *const return_type_annotation) + ir::TypeNode *const return_type_annotation, bool is_declare) { auto *const function_scope = binder->Allocator()->New(checker->Allocator(), param_scope); function_scope->BindParamScope(param_scope); param_scope->BindFunctionScope(function_scope); + auto flags = ir::ModifierFlags::PUBLIC; + + if (is_declare) { + body.clear(); + flags |= ir::ModifierFlags::DECLARE; + } + auto *const body_block = checker->Allocator()->New(checker->Allocator(), function_scope, std::move(body)); auto *const function = checker->Allocator()->New( function_scope, std::move(params), nullptr, body_block, return_type_annotation, ir::ScriptFunctionFlags::METHOD, - ir::ModifierFlags::PUBLIC, false, Language(Language::Id::ETS)); + flags, false, Language(Language::Id::ETS)); binder->AsETSBinder()->BuildInternalName(function); binder->AsETSBinder()->AddCompilableFunction(function); @@ -331,7 +338,7 @@ ETSEnumType::Method ETSChecker::CreateEnumFromIntMethod(ir::Identifier *const na auto *const enum_type_annotation = MakeTypeReference(Allocator(), enum_type->GetName()); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - enum_type_annotation); + enum_type_annotation, enum_type->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::FROM_INT_METHOD_NAME); @@ -367,7 +374,7 @@ ETSEnumType::Method ETSChecker::CreateEnumToStringMethod(ir::Identifier *const s auto *const string_type_annotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - string_type_annotation); + string_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::TO_STRING_METHOD_NAME); @@ -405,7 +412,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetValueMethod(ir::Identifier *const v auto *const int_type_annotation = Allocator()->New(ir::PrimitiveType::INT); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - int_type_annotation); + int_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::GET_VALUE_METHOD_NAME); @@ -443,7 +450,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetNameMethod(ir::Identifier *const na auto *const string_type_annotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - string_type_annotation); + string_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::GET_NAME_METHOD_NAME); @@ -565,7 +572,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na auto *const enum_type_annotation = MakeTypeReference(Allocator(), enum_type->GetName()); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - enum_type_annotation); + enum_type_annotation, enum_type->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const function_ident = @@ -597,7 +604,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValuesMethod(ir::Identifier *const ite Allocator()->New(MakeTypeReference(Allocator(), enum_type->GetName())); auto *const function = MakeFunction(this, Binder()->AsETSBinder(), param_scope, std::move(params), std::move(body), - enum_array_type_annotation); + enum_array_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::VALUES_METHOD_NAME); diff --git a/compiler/core/ETSCompiler.cpp b/compiler/core/ETSCompiler.cpp index c7f91c0d7962a2e2b8797f073f71b64e0e9c642f..7bc081cb61498825ca14b622e3744e7bfa5050b4 100644 --- a/compiler/core/ETSCompiler.cpp +++ b/compiler/core/ETSCompiler.cpp @@ -733,6 +733,12 @@ void ETSCompiler::Compile(const ir::TSImportEqualsDeclaration *st) const UNREACHABLE(); } +void ETSCompiler::Compile(const ir::etsNamespaceDeclaration *st) const +{ + (void)st; + UNREACHABLE(); +} + void ETSCompiler::Compile(const ir::TSImportType *node) const { (void)node; diff --git a/compiler/core/JSCompiler.cpp b/compiler/core/JSCompiler.cpp index a0b4815892d893a6432ee139e5fcea744c7a4b0c..7fdffdf883f1b48cab55ea810686e138928e20e9 100644 --- a/compiler/core/JSCompiler.cpp +++ b/compiler/core/JSCompiler.cpp @@ -994,6 +994,12 @@ void JSCompiler::Compile(const ir::TSBooleanKeyword *node) const UNREACHABLE(); } +void JSCompiler::Compile(const ir::etsNamespaceDeclaration *node) const +{ + (void)node; + UNREACHABLE(); +} + void JSCompiler::Compile(const ir::TSClassImplements *expr) const { (void)expr; diff --git a/ir/astNodeMapping.h b/ir/astNodeMapping.h index 245b7b86369526bbe12cb3b35558e5ef4b6e99de..06661aa3b50926f5ec3cb87d48372ab6218aebfb 100644 --- a/ir/astNodeMapping.h +++ b/ir/astNodeMapping.h @@ -87,6 +87,7 @@ _(ETS_NEW_MULTI_DIM_ARRAY_INSTANCE_EXPRESSION, ETSNewMultiDimArrayInstanceExpression) \ _(ETS_NEW_CLASS_INSTANCE_EXPRESSION, ETSNewClassInstanceExpression) \ _(ETS_IMPORT_DECLARATION, ETSImportDeclaration) \ + _(ETS_NAMESPACE_DECLARATION, etsNamespaceDeclaration) \ _(ETS_PARAMETER_EXPRESSION, ETSParameterExpression) \ _(SUPER_EXPRESSION, SuperExpression) \ _(STRUCT_DECLARATION, ETSStructDeclaration) \ diff --git a/ir/ets/etsNamespaceDeclaration.cpp b/ir/ets/etsNamespaceDeclaration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5bf215fc5a9e48fac6d51e221ce234ce293240b0 --- /dev/null +++ b/ir/ets/etsNamespaceDeclaration.cpp @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsNamespaceDeclaration.h" + +#include "checker/ETSchecker.h" +#include "binder/ETSBinder.h" +#include "ir/astDump.h" +#include "ir/expressions/identifier.h" +#include "ir/module/importDeclaration.h" +#include "ir/expressions/literals/stringLiteral.h" + +namespace panda::es2panda::ir { +void etsNamespaceDeclaration::TransformChildren(const NodeTransformer &cb) +{ + local_ = cb(local_)->AsIdentifier(); +} + +void etsNamespaceDeclaration::Iterate(const NodeTraverser &cb) const +{ + cb(local_); +} + +void etsNamespaceDeclaration::Dump(ir::AstDumper *dumper) const +{ + dumper->Add({{"type", "etsNamespaceDeclaration"}, {"local", local_}}); +} + +void etsNamespaceDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} + +checker::Type *etsNamespaceDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return nullptr; +} + +checker::Type *etsNamespaceDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +{ + if (Local()->Name().Empty()) { + return nullptr; + } + + if (Local()->AsIdentifier()->TsType() != nullptr) { + return local_->TsType(); + } + + auto *decl = Parent()->AsETSImportDeclaration(); + auto import_path = decl->Source()->Str(); + + if (decl->IsPureDynamic()) { + auto *type = checker->GlobalBuiltinDynamicType(decl->Language()); + checker->SetrModuleObjectTsType(local_, type); + return type; + } + + std::string package_name = import_path.Mutf8(); + std::replace(package_name.begin(), package_name.end(), '/', '.'); + util::UString package_path(package_name, checker->Allocator()); + std::vector synthetic_names = checker->GetNameForSynteticObjectType(package_path.View()); + + auto *module_object_type = + checker->Allocator()->New(checker->Allocator(), synthetic_names[0], synthetic_names[0], + local_->AsIdentifier(), checker::ETSObjectFlags::CLASS); + + auto *root_decl = checker->Allocator()->New(synthetic_names[0]); + binder::LocalVariable *root_var = + checker->Allocator()->New(root_decl, binder::VariableFlags::NONE); + root_var->SetTsType(module_object_type); + + synthetic_names.erase(synthetic_names.begin()); + checker::ETSObjectType *last_object_type(module_object_type); + + for (const auto &synthetic_name : synthetic_names) { + auto *synthetic_obj_type = + checker->Allocator()->New(checker->Allocator(), synthetic_name, synthetic_name, + local_->AsIdentifier(), checker::ETSObjectFlags::NO_OPTS); + + auto *class_decl = checker->Allocator()->New(synthetic_name); + binder::LocalVariable *var = + checker->Allocator()->New(class_decl, binder::VariableFlags::CLASS); + var->SetTsType(synthetic_obj_type); + last_object_type->AddProperty(var); + synthetic_obj_type->SetEnclosingType(last_object_type); + last_object_type = synthetic_obj_type; + } + + checker->SetPropertiesForModuleObject(last_object_type, import_path); + checker->SetrModuleObjectTsType(local_, last_object_type); + + return module_object_type; +} +} // namespace panda::es2panda::ir diff --git a/ir/ets/etsNamespaceDeclaration.h b/ir/ets/etsNamespaceDeclaration.h new file mode 100644 index 0000000000000000000000000000000000000000..8702fc1c6fd7a867aeab6d634c583d9cf53e728c --- /dev/null +++ b/ir/ets/etsNamespaceDeclaration.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ir/statement.h" + +namespace panda::es2panda::ir { +class Identifier; + +class etsNamespaceDeclaration : public Statement { +public: + explicit etsNamespaceDeclaration(Identifier *local) + : Statement(AstNodeType::ETS_NAMESPACE_DECLARATION), local_(local) + { + } + + Identifier *Local() + { + return local_; + } + + const Identifier *Local() const + { + return local_; + } + + void TransformChildren(const NodeTransformer &cb) override; + void Iterate(const NodeTraverser &cb) const override; + void Dump(ir::AstDumper *dumper) const override; + void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + +private: + Identifier *local_; +}; +} // namespace panda::es2panda::ir diff --git a/ir/ts/tsEnumDeclaration.h b/ir/ts/tsEnumDeclaration.h index 7661f213950e3f9d819dc497096eb8e2006ca26e..5caf2f0b66e366a755c0efea76ac1b3e5d72b780 100644 --- a/ir/ts/tsEnumDeclaration.h +++ b/ir/ts/tsEnumDeclaration.h @@ -31,17 +31,22 @@ class TSEnumMember; class TSEnumDeclaration : public TypedStatement { public: explicit TSEnumDeclaration(ArenaAllocator *allocator, binder::LocalScope *scope, Identifier *key, - ArenaVector &&members, bool is_const, bool is_static = false) + ArenaVector &&members, bool is_const, bool is_static = false, + bool is_declare = false) : TypedStatement(AstNodeType::TS_ENUM_DECLARATION), scope_(scope), decorators_(allocator->Adapter()), key_(key), members_(std::move(members)), - is_const_(is_const) + is_const_(is_const), + is_declare_(is_declare) { if (is_static) { AddModifier(ModifierFlags::STATIC); } + if (is_declare) { + AddModifier(ModifierFlags::DECLARE); + } } bool IsScopeBearer() const override @@ -84,6 +89,11 @@ public: return is_const_; } + bool IsDeclare() const + { + return is_declare_; + } + const ArenaVector &Decorators() const { return decorators_; @@ -117,6 +127,7 @@ private: ArenaVector members_; util::StringView internal_name_; bool is_const_; + bool is_declare_; }; } // namespace panda::es2panda::ir diff --git a/parser/ETSparser.cpp b/parser/ETSparser.cpp index bccc01c60a7dcc0bb5a8881908654e9ad0fc4ca9..438d8ad2102dd28bc20fde3394448cec3aedd3ff 100644 --- a/parser/ETSparser.cpp +++ b/parser/ETSparser.cpp @@ -4025,8 +4025,9 @@ ir::TSEnumDeclaration *ETSParser::ParseEnumMembers(ir::Identifier *const key, co ParseNumberEnum(members); } - auto *const enum_declaration = AllocNode(Allocator(), Binder()->GetScope()->AsLocalScope(), - key, std::move(members), is_const, is_static); + auto *const enum_declaration = + AllocNode(Allocator(), Binder()->GetScope()->AsLocalScope(), key, std::move(members), + is_const, is_static, InAmbientContext()); enum_declaration->SetRange({enum_start, Lexer()->GetToken().End()}); Lexer()->NextToken(); // eat '}' @@ -4371,6 +4372,7 @@ void ETSParser::CheckDeclare() case lexer::TokenType::KEYW_CLASS: case lexer::TokenType::KEYW_NAMESPACE: case lexer::TokenType::KEYW_ENUM: + case lexer::TokenType::KEYW_TYPE: case lexer::TokenType::KEYW_ABSTRACT: case lexer::TokenType::KEYW_INTERFACE: { return; diff --git a/test/parser/ets/declare_enum.ets b/test/parser/ets/declare_enum.ets new file mode 100644 index 0000000000000000000000000000000000000000..44b78d6bf6581f4ac7098e0a3aa3abe357d64772 --- /dev/null +++ b/test/parser/ets/declare_enum.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare enum Enum { + AAA, + BBB +} diff --git a/test/parser/ets/declare_namespace.ets b/test/parser/ets/declare_namespace.ets new file mode 100644 index 0000000000000000000000000000000000000000..eb8725b59b31134a0ab2ffd11424d157e0a92fa3 --- /dev/null +++ b/test/parser/ets/declare_namespace.ets @@ -0,0 +1,16 @@ +/* + * 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 name {} diff --git a/test/parser/ets/declare_namespace_2.ets b/test/parser/ets/declare_namespace_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..95d1612cb14002475a13b4b75d1d8744ddcc71d7 --- /dev/null +++ b/test/parser/ets/declare_namespace_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace { + function foo(); +} diff --git a/test/parser/ets/declare_type.ets b/test/parser/ets/declare_type.ets new file mode 100644 index 0000000000000000000000000000000000000000..550ed67dab54a24a39222f56a75178ec750e1a5e --- /dev/null +++ b/test/parser/ets/declare_type.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type t = int; diff --git a/test/parser/ets/declare_var_1.ets b/test/parser/ets/declare_var_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..f60810d582d3bdbc99f2910ab0c72b40020cc921 --- /dev/null +++ b/test/parser/ets/declare_var_1.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare const var: int diff --git a/test/parser/ets/declare_var_2.ets b/test/parser/ets/declare_var_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..4756694024a28f6779bb2a0642e58ed0707d4ac4 --- /dev/null +++ b/test/parser/ets/declare_var_2.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare let var: int