• 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 #include "ETSchecker.h"
17 
18 #include "es2panda.h"
19 #include "ir/base/classDefinition.h"
20 #include "ir/expression.h"
21 #include "ir/expressions/callExpression.h"
22 #include "ir/ts/tsInterfaceDeclaration.h"
23 #include "ir/statements/blockStatement.h"
24 #include "varbinder/ETSBinder.h"
25 #include "parser/program/program.h"
26 #include "checker/ets/aliveAnalyzer.h"
27 
28 #include "ir/base/scriptFunction.h"
29 #include "util/helpers.h"
30 
31 namespace panda::es2panda::checker {
InitializeBuiltins(varbinder::ETSBinder * varbinder)32 void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder)
33 {
34     if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) {
35         return;
36     }
37 
38     const auto varMap = varbinder->TopScope()->Bindings();
39 
40     auto initBuiltin = [varMap](ETSChecker *checker, std::string_view signature) -> util::StringView {
41         const auto iterator = varMap.find(signature);
42         ASSERT(iterator != varMap.end());
43         checker->GetGlobalTypesHolder()->InitializeBuiltin(
44             iterator->first,
45             checker->BuildClassProperties(iterator->second->Declaration()->Node()->AsClassDefinition()));
46         return iterator->first;
47     };
48 
49     auto const objectName = initBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS);
50     auto const voidName = initBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS);
51 
52     for (const auto &[name, var] : varMap) {
53         if (name == objectName || name == voidName) {
54             continue;
55         }
56 
57         if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) {
58             InitializeBuiltin(var, name);
59         }
60     }
61 
62     AddStatus(CheckerStatus::BUILTINS_INITIALIZED);
63 }
64 
InitializeBuiltin(varbinder::Variable * var,const util::StringView & name)65 void ETSChecker::InitializeBuiltin(varbinder::Variable *var, const util::StringView &name)
66 {
67     Type *type {nullptr};
68     if (var->Declaration()->Node()->IsClassDefinition()) {
69         type = BuildClassProperties(var->Declaration()->Node()->AsClassDefinition());
70     } else {
71         ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration());
72         type = BuildInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration());
73     }
74     GetGlobalTypesHolder()->InitializeBuiltin(name, type);
75 }
76 
StartChecker(varbinder::VarBinder * varbinder,const CompilerOptions & options)77 bool ETSChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const CompilerOptions &options)
78 {
79     Initialize(varbinder);
80 
81     if (options.dumpAst) {
82         std::cout << Program()->Dump() << std::endl;
83     }
84 
85     if (options.opDumpAstOnlySilent) {
86         Program()->DumpSilent();
87         return false;
88     }
89 
90     if (options.parseOnly) {
91         return false;
92     }
93 
94     varbinder->SetGenStdLib(options.compilationMode == CompilationMode::GEN_STD_LIB);
95     varbinder->IdentifierAnalysis();
96 
97     auto *etsBinder = varbinder->AsETSBinder();
98     InitializeBuiltins(etsBinder);
99 
100     for (auto &entry : etsBinder->DynamicImportVars()) {
101         auto &data = entry.second;
102         if (data.import->IsPureDynamic()) {
103             data.variable->SetTsType(GlobalBuiltinDynamicType(data.import->Language()));
104         }
105     }
106 
107     CheckProgram(Program(), true);
108 
109     BuildDynamicCallClass(true);
110     BuildDynamicCallClass(false);
111 
112     BuildDynamicImportClass();
113 
114 #ifndef NDEBUG
115     for (auto lambda : etsBinder->LambdaObjects()) {
116         ASSERT(!lambda.second.first->TsType()->AsETSObjectType()->AssemblerName().Empty());
117     }
118     for (auto *func : varbinder->Functions()) {
119         ASSERT(!func->Node()->AsScriptFunction()->Scope()->InternalName().Empty());
120     }
121 #endif
122 
123     if (options.dumpCheckedAst) {
124         std::cout << Program()->Dump() << std::endl;
125     }
126 
127     return true;
128 }
129 
CheckProgram(parser::Program * program,bool runAnalysis)130 void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis)
131 {
132     auto *savedProgram = Program();
133     SetProgram(program);
134 
135     for (auto &[_, extPrograms] : program->ExternalSources()) {
136         (void)_;
137         for (auto *extProg : extPrograms) {
138             CheckProgram(extProg);
139         }
140     }
141 
142     ASSERT(Program()->Ast()->IsProgram());
143     Program()->Ast()->Check(this);
144 
145     if (runAnalysis) {
146         AliveAnalyzer(Program()->Ast(), this);
147     }
148 
149     ASSERT(VarBinder()->AsETSBinder()->GetExternalRecordTable().find(program)->second);
150 
151     SetProgram(savedProgram);
152 }
153 
CheckTypeCached(ir::Expression * expr)154 Type *ETSChecker::CheckTypeCached(ir::Expression *expr)
155 {
156     if (expr->TsType() == nullptr) {
157         expr->SetTsType(expr->Check(this));
158     }
159 
160     return expr->TsType();
161 }
162 
AsETSObjectType(Type * (GlobalTypesHolder::* typeFunctor)()) const163 ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const
164 {
165     auto *ret = (GetGlobalTypesHolder()->*typeFunctor)();
166     return ret != nullptr ? ret->AsETSObjectType() : nullptr;
167 }
168 
GlobalByteType() const169 Type *ETSChecker::GlobalByteType() const
170 {
171     return GetGlobalTypesHolder()->GlobalByteType();
172 }
173 
GlobalShortType() const174 Type *ETSChecker::GlobalShortType() const
175 {
176     return GetGlobalTypesHolder()->GlobalShortType();
177 }
178 
GlobalIntType() const179 Type *ETSChecker::GlobalIntType() const
180 {
181     return GetGlobalTypesHolder()->GlobalIntType();
182 }
183 
GlobalLongType() const184 Type *ETSChecker::GlobalLongType() const
185 {
186     return GetGlobalTypesHolder()->GlobalLongType();
187 }
188 
GlobalFloatType() const189 Type *ETSChecker::GlobalFloatType() const
190 {
191     return GetGlobalTypesHolder()->GlobalFloatType();
192 }
193 
GlobalDoubleType() const194 Type *ETSChecker::GlobalDoubleType() const
195 {
196     return GetGlobalTypesHolder()->GlobalDoubleType();
197 }
198 
GlobalCharType() const199 Type *ETSChecker::GlobalCharType() const
200 {
201     return GetGlobalTypesHolder()->GlobalCharType();
202 }
203 
GlobalETSBooleanType() const204 Type *ETSChecker::GlobalETSBooleanType() const
205 {
206     return GetGlobalTypesHolder()->GlobalETSBooleanType();
207 }
208 
GlobalVoidType() const209 Type *ETSChecker::GlobalVoidType() const
210 {
211     return GetGlobalTypesHolder()->GlobalETSVoidType();
212 }
213 
GlobalETSNullType() const214 Type *ETSChecker::GlobalETSNullType() const
215 {
216     return GetGlobalTypesHolder()->GlobalETSNullType();
217 }
218 
GlobalETSUndefinedType() const219 Type *ETSChecker::GlobalETSUndefinedType() const
220 {
221     return GetGlobalTypesHolder()->GlobalETSUndefinedType();
222 }
223 
GlobalETSStringLiteralType() const224 Type *ETSChecker::GlobalETSStringLiteralType() const
225 {
226     return GetGlobalTypesHolder()->GlobalETSStringLiteralType();
227 }
228 
GlobalETSBigIntType() const229 Type *ETSChecker::GlobalETSBigIntType() const
230 {
231     return GetGlobalTypesHolder()->GlobalETSBigIntBuiltinType();
232 }
233 
GlobalWildcardType() const234 Type *ETSChecker::GlobalWildcardType() const
235 {
236     return GetGlobalTypesHolder()->GlobalWildcardType();
237 }
238 
GlobalETSObjectType() const239 ETSObjectType *ETSChecker::GlobalETSObjectType() const
240 {
241     return AsETSObjectType(&GlobalTypesHolder::GlobalETSObjectType);
242 }
243 
GlobalETSNullishObjectType() const244 ETSObjectType *ETSChecker::GlobalETSNullishObjectType() const
245 {
246     return AsETSObjectType(&GlobalTypesHolder::GlobalETSNullishObjectType);
247 }
248 
GlobalBuiltinETSStringType() const249 ETSObjectType *ETSChecker::GlobalBuiltinETSStringType() const
250 {
251     return AsETSObjectType(&GlobalTypesHolder::GlobalETSStringBuiltinType);
252 }
253 
GlobalBuiltinETSBigIntType() const254 ETSObjectType *ETSChecker::GlobalBuiltinETSBigIntType() const
255 {
256     return AsETSObjectType(&GlobalTypesHolder::GlobalETSBigIntBuiltinType);
257 }
258 
GlobalBuiltinTypeType() const259 ETSObjectType *ETSChecker::GlobalBuiltinTypeType() const
260 {
261     return AsETSObjectType(&GlobalTypesHolder::GlobalTypeBuiltinType);
262 }
263 
GlobalBuiltinExceptionType() const264 ETSObjectType *ETSChecker::GlobalBuiltinExceptionType() const
265 {
266     return AsETSObjectType(&GlobalTypesHolder::GlobalExceptionBuiltinType);
267 }
268 
GlobalBuiltinErrorType() const269 ETSObjectType *ETSChecker::GlobalBuiltinErrorType() const
270 {
271     return AsETSObjectType(&GlobalTypesHolder::GlobalErrorBuiltinType);
272 }
273 
GlobalStringBuilderBuiltinType() const274 ETSObjectType *ETSChecker::GlobalStringBuilderBuiltinType() const
275 {
276     return AsETSObjectType(&GlobalTypesHolder::GlobalStringBuilderBuiltinType);
277 }
278 
GlobalBuiltinPromiseType() const279 ETSObjectType *ETSChecker::GlobalBuiltinPromiseType() const
280 {
281     return AsETSObjectType(&GlobalTypesHolder::GlobalPromiseBuiltinType);
282 }
283 
GlobalBuiltinJSRuntimeType() const284 ETSObjectType *ETSChecker::GlobalBuiltinJSRuntimeType() const
285 {
286     return AsETSObjectType(&GlobalTypesHolder::GlobalJSRuntimeBuiltinType);
287 }
288 
GlobalBuiltinJSValueType() const289 ETSObjectType *ETSChecker::GlobalBuiltinJSValueType() const
290 {
291     return AsETSObjectType(&GlobalTypesHolder::GlobalJSValueBuiltinType);
292 }
293 
GlobalBuiltinVoidType() const294 ETSObjectType *ETSChecker::GlobalBuiltinVoidType() const
295 {
296     return AsETSObjectType(&GlobalTypesHolder::GlobalBuiltinVoidType);
297 }
298 
GlobalBuiltinDynamicType(Language lang) const299 ETSObjectType *ETSChecker::GlobalBuiltinDynamicType(Language lang) const
300 {
301     if (lang.GetId() == Language::Id::JS) {
302         return GlobalBuiltinJSValueType();
303     }
304     return nullptr;
305 }
306 
GlobalBuiltinBoxType(const Type * contents) const307 ETSObjectType *ETSChecker::GlobalBuiltinBoxType(const Type *contents) const
308 {
309     switch (TypeKind(contents)) {
310         case TypeFlag::ETS_BOOLEAN:
311             return AsETSObjectType(&GlobalTypesHolder::GlobalBooleanBoxBuiltinType);
312         case TypeFlag::BYTE:
313             return AsETSObjectType(&GlobalTypesHolder::GlobalByteBoxBuiltinType);
314         case TypeFlag::CHAR:
315             return AsETSObjectType(&GlobalTypesHolder::GlobalCharBoxBuiltinType);
316         case TypeFlag::SHORT:
317             return AsETSObjectType(&GlobalTypesHolder::GlobalShortBoxBuiltinType);
318         case TypeFlag::INT:
319             return AsETSObjectType(&GlobalTypesHolder::GlobalIntBoxBuiltinType);
320         case TypeFlag::LONG:
321             return AsETSObjectType(&GlobalTypesHolder::GlobalLongBoxBuiltinType);
322         case TypeFlag::FLOAT:
323             return AsETSObjectType(&GlobalTypesHolder::GlobalFloatBoxBuiltinType);
324         case TypeFlag::DOUBLE:
325             return AsETSObjectType(&GlobalTypesHolder::GlobalDoubleBoxBuiltinType);
326         default:
327             return AsETSObjectType(&GlobalTypesHolder::GlobalBoxBuiltinType);
328     }
329 }
330 
PrimitiveWrapper() const331 const checker::WrapperDesc &ETSChecker::PrimitiveWrapper() const
332 {
333     return primitiveWrappers_.Wrappers();
334 }
335 
GlobalArrayTypes()336 GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes()
337 {
338     return globalArraySignatures_;
339 }
340 
GlobalArrayTypes() const341 const GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes() const
342 {
343     return globalArraySignatures_;
344 }
345 
346 // For use in Signature::ToAssemblerType
MaybeBoxedType(Checker * checker,const varbinder::Variable * var)347 const Type *MaybeBoxedType(Checker *checker, const varbinder::Variable *var)
348 {
349     return checker->AsETSChecker()->MaybeBoxedType(var);
350 }
351 
HandleUpdatedCallExpressionNode(ir::CallExpression * callExpr)352 void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr)
353 {
354     VarBinder()->AsETSBinder()->HandleCustomNodes(callExpr);
355 }
356 
SelectGlobalIntegerTypeForNumeric(Type * type)357 Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type)
358 {
359     switch (ETSType(type)) {
360         case checker::TypeFlag::FLOAT: {
361             return GlobalIntType();
362         }
363         case checker::TypeFlag::DOUBLE: {
364             return GlobalLongType();
365         }
366         default: {
367             return type;
368         }
369     }
370 }
371 
372 }  // namespace panda::es2panda::checker
373