• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 //
17 // desc: Object index access syntax is translated to the call of special setter (in case of assignment):
18 //       `obj[i] = val;` => `obj.S_set(i, val);`
19 //   	 or getter (in all the other cases):
20 //   	 ...obj[i]... => ...obj.S_get(i)...
21 //      methods.
22 //
23 
24 #include "objectIndexAccess.h"
25 
26 #include "checker/ETSchecker.h"
27 #include "compiler/core/ASTVerifier.h"
28 #include "parser/ETSparser.h"
29 
30 namespace panda::es2panda::compiler {
ProcessIndexSetAccess(parser::ETSParser * parser,checker::ETSChecker * checker,ir::AssignmentExpression * assignmentExpression) const31 ir::Expression *ObjectIndexLowering::ProcessIndexSetAccess(parser::ETSParser *parser, checker::ETSChecker *checker,
32                                                            ir::AssignmentExpression *assignmentExpression) const
33 {
34     //  Note! We assume that parser and checker phase nave been already passed correctly, thus the class has
35     //  required accessible index method[s] and all the types are properly resolved.
36     static std::string const CALL_EXPRESSION =
37         std::string {"@@E1."} + std::string {compiler::Signatures::SET_INDEX_METHOD} + "(@@E2, @@E3)";
38 
39     // Parse ArkTS code string and create and process corresponding AST node(s)
40     auto *const memberExpression = assignmentExpression->Left()->AsMemberExpression();
41     auto *const loweringResult =
42         parser->CreateFormattedExpression(CALL_EXPRESSION, parser::DEFAULT_SOURCE_FILE, memberExpression->Object(),
43                                           memberExpression->Property(), assignmentExpression->Right());
44     loweringResult->SetParent(assignmentExpression->Parent());
45 
46     loweringResult->Check(checker);
47     return loweringResult;
48 }
49 
ProcessIndexGetAccess(parser::ETSParser * parser,checker::ETSChecker * checker,ir::MemberExpression * memberExpression) const50 ir::Expression *ObjectIndexLowering::ProcessIndexGetAccess(parser::ETSParser *parser, checker::ETSChecker *checker,
51                                                            ir::MemberExpression *memberExpression) const
52 {
53     //  Note! We assume that parser and checker phase nave been already passed correctly, thus the class has
54     //  required accessible index method[s] and all the types are properly resolved.
55     static std::string const CALL_EXPRESSION =
56         std::string {"@@E1."} + std::string {compiler::Signatures::GET_INDEX_METHOD} + "(@@E2)";
57 
58     // Parse ArkTS code string and create and process corresponding AST node(s)
59     auto *const loweringResult = parser->CreateFormattedExpression(
60         CALL_EXPRESSION, parser::DEFAULT_SOURCE_FILE, memberExpression->Object(), memberExpression->Property());
61     loweringResult->SetParent(memberExpression->Parent());
62 
63     loweringResult->Check(checker);
64     loweringResult->SetBoxingUnboxingFlags(memberExpression->GetBoxingUnboxingFlags());
65     return loweringResult;
66 }
67 
Perform(public_lib::Context * ctx,parser::Program * program)68 bool ObjectIndexLowering::Perform(public_lib::Context *ctx, parser::Program *program)
69 {
70     if (ctx->compilerContext->Options()->compilationMode == CompilationMode::GEN_STD_LIB) {
71         for (auto &[_, extPrograms] : program->ExternalSources()) {
72             (void)_;
73             for (auto *extProg : extPrograms) {
74                 Perform(ctx, extProg);
75             }
76         }
77     }
78 
79     auto *const parser = ctx->parser->AsETSParser();
80     ASSERT(parser != nullptr);
81     auto *const checker = ctx->checker->AsETSChecker();
82     ASSERT(checker != nullptr);
83 
84     program->Ast()->TransformChildrenRecursively([this, parser, checker](ir::AstNode *const ast) -> ir::AstNode * {
85         if (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->Left()->IsMemberExpression() &&
86             ast->AsAssignmentExpression()->Left()->AsMemberExpression()->Kind() ==
87                 ir::MemberExpressionKind::ELEMENT_ACCESS) {
88             if (auto const *const objectType = ast->AsAssignmentExpression()->Left()->AsMemberExpression()->ObjType();
89                 objectType != nullptr && !objectType->IsETSDynamicType()) {
90                 return ProcessIndexSetAccess(parser, checker, ast->AsAssignmentExpression());
91             }
92         }
93         return ast;
94     });
95 
96     program->Ast()->TransformChildrenRecursively([this, parser, checker](ir::AstNode *const ast) -> ir::AstNode * {
97         if (ast->IsMemberExpression() &&
98             ast->AsMemberExpression()->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) {
99             if (auto const *const objectType = ast->AsMemberExpression()->ObjType();
100                 objectType != nullptr && !objectType->IsETSDynamicType()) {
101                 return ProcessIndexGetAccess(parser, checker, ast->AsMemberExpression());
102             }
103         }
104         return ast;
105     });
106 
107     return true;
108 }
109 
Postcondition(public_lib::Context * ctx,const parser::Program * program)110 bool ObjectIndexLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program)
111 {
112     if (ctx->compilerContext->Options()->compilationMode == CompilationMode::GEN_STD_LIB) {
113         for (auto &[_, extPrograms] : program->ExternalSources()) {
114             (void)_;
115             for (auto *extProg : extPrograms) {
116                 if (!Postcondition(ctx, extProg)) {
117                     return false;
118                 }
119             }
120         }
121     }
122 
123     return !program->Ast()->IsAnyChild([](const ir::AstNode *ast) {
124         if (ast->IsMemberExpression() &&
125             ast->AsMemberExpression()->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) {
126             if (auto const *const objectType = ast->AsMemberExpression()->ObjType(); objectType != nullptr) {
127                 return !objectType->IsETSDynamicType();
128             }
129         }
130         return false;
131     });
132 }
133 
134 }  // namespace panda::es2panda::compiler
135