13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "ambientLowering.h" 173af6ab5fSopenharmony_ci#include <string_view> 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ci#include "ir/expressions/dummyNode.h" 203af6ab5fSopenharmony_ci#include "ir/astNode.h" 213af6ab5fSopenharmony_ci 223af6ab5fSopenharmony_cinamespace ark::es2panda::compiler { 233af6ab5fSopenharmony_cistd::string_view AmbientLowering::Name() const 243af6ab5fSopenharmony_ci{ 253af6ab5fSopenharmony_ci static std::string const NAME = "AmbientLowering"; 263af6ab5fSopenharmony_ci return NAME; 273af6ab5fSopenharmony_ci} 283af6ab5fSopenharmony_ci 293af6ab5fSopenharmony_cibool AmbientLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) 303af6ab5fSopenharmony_ci{ 313af6ab5fSopenharmony_ci for (auto &[_, extPrograms] : program->ExternalSources()) { 323af6ab5fSopenharmony_ci (void)_; 333af6ab5fSopenharmony_ci for (auto *extProg : extPrograms) { 343af6ab5fSopenharmony_ci if (!Postcondition(ctx, extProg)) { 353af6ab5fSopenharmony_ci return false; 363af6ab5fSopenharmony_ci } 373af6ab5fSopenharmony_ci } 383af6ab5fSopenharmony_ci } 393af6ab5fSopenharmony_ci 403af6ab5fSopenharmony_ci return !program->Ast()->IsAnyChild( 413af6ab5fSopenharmony_ci [](const ir::AstNode *node) -> bool { return node->IsDummyNode() && node->AsDummyNode()->IsAmbientIndexer(); }); 423af6ab5fSopenharmony_ci} 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_cibool AmbientLowering::Perform(public_lib::Context *ctx, parser::Program *program) 453af6ab5fSopenharmony_ci{ 463af6ab5fSopenharmony_ci for (auto &[_, extPrograms] : program->ExternalSources()) { 473af6ab5fSopenharmony_ci (void)_; 483af6ab5fSopenharmony_ci for (auto *extProg : extPrograms) { 493af6ab5fSopenharmony_ci Perform(ctx, extProg); 503af6ab5fSopenharmony_ci } 513af6ab5fSopenharmony_ci } 523af6ab5fSopenharmony_ci 533af6ab5fSopenharmony_ci // Generate $_get and $_set for ambient Indexer 543af6ab5fSopenharmony_ci program->Ast()->TransformChildrenRecursively( 553af6ab5fSopenharmony_ci [this, ctx](ir::AstNode *ast) -> ir::AstNode * { 563af6ab5fSopenharmony_ci if (ast->IsClassDefinition()) { 573af6ab5fSopenharmony_ci return CreateIndexerMethodIfNeeded(ast->AsClassDefinition(), ctx); 583af6ab5fSopenharmony_ci } 593af6ab5fSopenharmony_ci return ast; 603af6ab5fSopenharmony_ci }, 613af6ab5fSopenharmony_ci Name()); 623af6ab5fSopenharmony_ci 633af6ab5fSopenharmony_ci return true; 643af6ab5fSopenharmony_ci} 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ciir::MethodDefinition *CreateMethodFunctionDefinition(ir::DummyNode *node, public_lib::Context *ctx, 673af6ab5fSopenharmony_ci ir::MethodDefinitionKind funcKind) 683af6ab5fSopenharmony_ci{ 693af6ab5fSopenharmony_ci auto parser = ctx->parser->AsETSParser(); 703af6ab5fSopenharmony_ci 713af6ab5fSopenharmony_ci auto const indexName = node->GetIndexName(); 723af6ab5fSopenharmony_ci auto const returnType = node->GetReturnTypeLiteral()->AsETSTypeReferencePart()->Name()->AsIdentifier()->Name(); 733af6ab5fSopenharmony_ci std::string sourceCode; 743af6ab5fSopenharmony_ci if (funcKind == ir::MethodDefinitionKind::GET) { 753af6ab5fSopenharmony_ci sourceCode = "$_get(" + std::string(indexName) + " : number) : " + std::string(returnType); 763af6ab5fSopenharmony_ci } else if (funcKind == ir::MethodDefinitionKind::SET) { 773af6ab5fSopenharmony_ci sourceCode = 783af6ab5fSopenharmony_ci "$_set(" + std::string(indexName) + " : number, " + "value : " + std::string(returnType) + " ) : void"; 793af6ab5fSopenharmony_ci } else { 803af6ab5fSopenharmony_ci UNREACHABLE(); 813af6ab5fSopenharmony_ci } 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_ci auto methodDefinition = parser->CreateFormattedClassMethodDefinition(sourceCode); 843af6ab5fSopenharmony_ci 853af6ab5fSopenharmony_ci methodDefinition->SetRange(node->Range()); 863af6ab5fSopenharmony_ci methodDefinition->SetParent(node->Parent()); 873af6ab5fSopenharmony_ci methodDefinition->AddModifier(ir::ModifierFlags::DECLARE); 883af6ab5fSopenharmony_ci return methodDefinition->AsMethodDefinition(); 893af6ab5fSopenharmony_ci} 903af6ab5fSopenharmony_ci 913af6ab5fSopenharmony_ciir::ClassDefinition *AmbientLowering::CreateIndexerMethodIfNeeded(ir::ClassDefinition *classDef, 923af6ab5fSopenharmony_ci public_lib::Context *ctx) 933af6ab5fSopenharmony_ci{ 943af6ab5fSopenharmony_ci auto &classBody = classDef->Body(); 953af6ab5fSopenharmony_ci auto it = classBody.begin(); 963af6ab5fSopenharmony_ci // Only one DummyNode is allowed in classBody for now 973af6ab5fSopenharmony_ci ASSERT(std::count_if(classBody.begin(), classBody.end(), [](ir::AstNode *node) { return node->IsDummyNode(); }) <= 983af6ab5fSopenharmony_ci 1); 993af6ab5fSopenharmony_ci while (it != classBody.end()) { 1003af6ab5fSopenharmony_ci if ((*it)->IsDummyNode() && (*it)->AsDummyNode()->IsAmbientIndexer()) { 1013af6ab5fSopenharmony_ci auto setDefinition = 1023af6ab5fSopenharmony_ci CreateMethodFunctionDefinition((*it)->AsDummyNode(), ctx, ir::MethodDefinitionKind::SET); 1033af6ab5fSopenharmony_ci auto getDefinition = 1043af6ab5fSopenharmony_ci CreateMethodFunctionDefinition((*it)->AsDummyNode(), ctx, ir::MethodDefinitionKind::GET); 1053af6ab5fSopenharmony_ci 1063af6ab5fSopenharmony_ci classBody.erase(it); 1073af6ab5fSopenharmony_ci classBody.emplace_back(setDefinition); 1083af6ab5fSopenharmony_ci classBody.emplace_back(getDefinition); 1093af6ab5fSopenharmony_ci break; 1103af6ab5fSopenharmony_ci } 1113af6ab5fSopenharmony_ci ++it; 1123af6ab5fSopenharmony_ci } 1133af6ab5fSopenharmony_ci 1143af6ab5fSopenharmony_ci return classDef; 1153af6ab5fSopenharmony_ci} 1163af6ab5fSopenharmony_ci} // namespace ark::es2panda::compiler 117