• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 "typeFromLowering.h"
17 
18 #include "checker/ETSchecker.h"
19 #include "checker/types/ets/etsTupleType.h"
20 #include "compiler/lowering/util.h"
21 #include "compiler/lowering/scopesInit/scopesInitPhase.h"
22 #include "ir/astNode.h"
23 
24 namespace ark::es2panda::compiler {
25 
26 using AstNodePtr = ir::AstNode *;
27 
Name() const28 std::string_view TypeFromLowering::Name() const
29 {
30     return "TypeFromLowering";
31 }
32 
TypeToString(const std::string & name)33 static std::string TypeToString(const std::string &name)
34 {
35     std::string src {"Type.resolve"};
36     src += "(\"";
37     src += name;
38     src += "\") as Type";
39     return src;
40 }
41 
PrimitiveTypeToString(const checker::Type * type,checker::ETSChecker * checker)42 std::string PrimitiveTypeToString(const checker::Type *type, checker::ETSChecker *checker)
43 {
44     switch (checker->TypeKind(type)) {
45         case checker::TypeFlag::ETS_BOOLEAN:
46             return std::string(compiler::Signatures::BOOLEANTYPE_VAL);
47         case checker::TypeFlag::BYTE:
48             return std::string(compiler::Signatures::BYTETYPE_VAL);
49         case checker::TypeFlag::CHAR:
50             return std::string(compiler::Signatures::CHARTYPE_VAL);
51         case checker::TypeFlag::SHORT:
52             return std::string(compiler::Signatures::SHORTTYPE_VAL);
53         case checker::TypeFlag::INT:
54             return std::string(compiler::Signatures::INTTYPE_VAL);
55         case checker::TypeFlag::LONG:
56             return std::string(compiler::Signatures::LONGTYPE_VAL);
57         case checker::TypeFlag::FLOAT:
58             return std::string(compiler::Signatures::FLOATTYPE_VAL);
59         case checker::TypeFlag::DOUBLE:
60             return std::string(compiler::Signatures::DOUBLETYPE_VAL);
61         case checker::TypeFlag::ETS_VOID:
62             return std::string(compiler::Signatures::VOIDTYPE_VAL);
63         default:
64             ES2PANDA_UNREACHABLE();
65     }
66 }
67 
HandleSpecialTypes(checker::Type * type)68 std::string HandleSpecialTypes(checker::Type *type)
69 {
70     if (type->IsETSUndefinedType()) {
71         return std::string(compiler::Signatures::UNDEFINEDTYPE_REF);
72     }
73 
74     if (type->IsETSNullType()) {
75         return std::string(compiler::Signatures::NULLTYPE_REF);
76     }
77 
78     if (type->IsETSVoidType()) {
79         return std::string(compiler::Signatures::VOIDTYPE_VAL);
80     }
81     return "";
82 }
83 
IsTypeFrom(ir::Expression * callee)84 static bool IsTypeFrom(ir::Expression *callee)
85 {
86     if (!callee->IsMemberExpression()) {
87         return false;
88     }
89 
90     auto *memberExpr = callee->AsMemberExpression();
91     return memberExpr->HasMemberKind(ir::MemberExpressionKind::PROPERTY_ACCESS) &&
92            memberExpr->Object()->IsIdentifier() &&
93            memberExpr->Object()->AsIdentifier()->Name() == compiler::Signatures::TYPE &&
94            memberExpr->Property()->IsIdentifier() &&
95            memberExpr->Property()->AsIdentifier()->Name() == compiler::Signatures::FROM;
96 }
97 
HandleTypeParameter(ir::Expression * param,checker::ETSChecker * checker)98 std::string HandleTypeParameter(ir::Expression *param, checker::ETSChecker *checker)
99 {
100     auto *source = param->TsType();
101     if (source->IsETSObjectType()) {
102         return TypeToString(std::string(source->AsETSObjectType()->AssemblerName()));
103     }
104 
105     if (source->IsETSPrimitiveType()) {
106         return PrimitiveTypeToString(source, checker);
107     }
108 
109     if (source->IsETSArrayType()) {
110         return TypeToString(std::string(compiler::Signatures::ESCOMPAT_ARRAY));
111     }
112 
113     return HandleSpecialTypes(source);
114 }
115 
ReplaceTypeFrom(public_lib::Context * ctx,ir::CallExpression * ast)116 ir::Expression *ReplaceTypeFrom(public_lib::Context *ctx, ir::CallExpression *ast)
117 {
118     auto parser = ctx->parser->AsETSParser();
119     auto checker = ctx->checker->AsETSChecker();
120     auto *typeParams = ast->AsCallExpression()->TypeParams();
121 
122     ES2PANDA_ASSERT(typeParams != nullptr && typeParams->Params().size() == 1);
123 
124     auto *param = typeParams->Params().front();
125     if (param->IsETSUnionType()) {
126         checker->LogError(diagnostic::TYPE_FROM_UNION_TYPE_UNSUPPORTED, {}, ast->Start());
127         return ast;
128     }
129 
130     if (param->IsETSTuple()) {
131         checker->LogError(diagnostic::TYPE_FROM_TUPLE_TYPE_UNSUPPORTED, {}, ast->Start());
132         return ast;
133     }
134 
135     if (param->IsETSStringLiteralType()) {
136         checker->LogError(diagnostic::TYPE_FROM_STRING_LITERAL_TYPE_UNSUPPORTED, {}, ast->Start());
137         return ast;
138     }
139 
140     std::string src = HandleTypeParameter(param, checker);
141     if (src.empty()) {
142         checker->LogError(diagnostic::TYPE_FROM_UNRESOLVABLE_TYPE, {}, ast->Start());
143         return ast;
144     }
145 
146     auto loweringResult = parser->CreateExpression(src);
147     loweringResult->SetParent(ast->Parent());
148 
149     InitScopesPhaseETS::RunExternalNode(loweringResult, checker->VarBinder());
150     checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(loweringResult, NearestScope(loweringResult));
151     loweringResult->Check(checker);
152     return loweringResult;
153 }
154 
PerformForModule(public_lib::Context * ctx,parser::Program * program)155 bool TypeFromLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program)
156 {
157     program->Ast()->TransformChildrenRecursively(
158         // CC-OFFNXT(G.FMT.14-CPP) project code style
159         [ctx](ir::AstNode *ast) -> AstNodePtr {
160             if (ast->IsCallExpression() && IsTypeFrom(ast->AsCallExpression()->Callee())) {
161                 return ReplaceTypeFrom(ctx, ast->AsCallExpression());
162             }
163             return ast;
164         },
165         Name());
166 
167     return true;
168 }
169 }  // namespace ark::es2panda::compiler
170