1 /*
2 * Copyright (c) 2023-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 #include "expandBrackets.h"
17
18 #include "checker/ETSchecker.h"
19 #include "compiler/lowering/util.h"
20 #include "compiler/lowering/scopesInit/scopesInitPhase.h"
21 #include "ir/statements/blockStatement.h"
22 #include "ir/expressions/memberExpression.h"
23 #include "parser/ETSparser.h"
24 #include "varbinder/ETSBinder.h"
25
26 namespace panda::es2panda::compiler {
27
Perform(public_lib::Context * ctx,parser::Program * program)28 bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *program)
29 {
30 auto *const checker = ctx->checker->AsETSChecker();
31 auto *const allocator = checker->Allocator();
32 auto *const parser = ctx->parser->AsETSParser();
33
34 program->Ast()->TransformChildrenRecursively([ctx, parser, checker, allocator](ir::AstNode *ast) -> ir::AstNode * {
35 if (!ast->IsETSNewArrayInstanceExpression()) {
36 return ast;
37 }
38 auto *newExpression = ast->AsETSNewArrayInstanceExpression();
39 auto *dimension = newExpression->Dimension();
40 auto *dimType = dimension->TsType();
41 if (auto *unboxed = checker->ETSBuiltinTypeAsPrimitiveType(dimType); unboxed != nullptr) {
42 dimType = unboxed;
43 }
44 if (!dimType->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) {
45 return ast;
46 }
47
48 auto *castedDimension =
49 parser->CreateFormattedExpression("@@E1 as int", parser::DEFAULT_SOURCE_FILE, dimension);
50 castedDimension->Check(checker);
51 castedDimension->SetParent(dimension->Parent());
52 newExpression->SetDimension(castedDimension);
53
54 auto *const scope = NearestScope(newExpression);
55 auto expressionCtx = varbinder::LexicalScope<varbinder::Scope>::Enter(checker->VarBinder(), scope);
56 auto *ident = Gensym(allocator);
57 auto *exprType = checker->AllocNode<ir::OpaqueTypeNode>(dimType);
58 auto *sequenceExpr = parser->CreateFormattedExpression(
59 "let @@I1 = (@@E2) as @@T3;"
60 "if (!isSafeInteger(@@I4)) {"
61 " throw new TypeError(\"Index fractional part should not be different from 0.0\");"
62 "};"
63 "(@@E5);",
64 parser::DEFAULT_SOURCE_FILE, ident, dimension, exprType, ident->Clone(allocator), newExpression);
65 sequenceExpr->SetParent(newExpression->Parent());
66 InitScopesPhaseETS::RunExternalNode(sequenceExpr, ctx->compilerContext->VarBinder());
67 checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequenceExpr, scope);
68 sequenceExpr->Check(checker);
69
70 return sequenceExpr;
71 });
72 return true;
73 }
74
75 } // namespace panda::es2panda::compiler
76