• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 2023 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 "ETSBinder.h"
17 
18 #include "ir/expressions/identifier.h"
19 #include "ir/expressions/thisExpression.h"
20 #include "ir/expressions/memberExpression.h"
21 #include "ir/expressions/callExpression.h"
22 #include "ir/expressions/functionExpression.h"
23 #include "ir/base/methodDefinition.h"
24 #include "ir/base/scriptFunction.h"
25 #include "ir/base/classElement.h"
26 #include "ir/base/classDefinition.h"
27 #include "ir/base/classProperty.h"
28 #include "ir/base/classStaticBlock.h"
29 #include "ir/statements/blockStatement.h"
30 #include "ir/statements/classDeclaration.h"
31 #include "ir/statements/variableDeclarator.h"
32 #include "ir/statements/functionDeclaration.h"
33 #include "ir/statements/returnStatement.h"
34 #include "ir/ets/etsPrimitiveType.h"
35 #include "ir/ets/etsTypeReferencePart.h"
36 #include "ir/ets/etsNewClassInstanceExpression.h"
37 #include "ir/ets/etsTypeReference.h"
38 #include "ir/ets/etsFunctionType.h"
39 #include "ir/ets/etsScript.h"
40 #include "ir/ets/etsImportDeclaration.h"
41 #include "ir/ts/tsInterfaceDeclaration.h"
42 #include "ir/ts/tsTypeParameterDeclaration.h"
43 #include "ir/ts/tsTypeParameterInstantiation.h"
44 #include "ir/ts/tsClassImplements.h"
45 #include "ir/ts/tsEnumDeclaration.h"
46 #include "ir/ts/tsEnumMember.h"
47 #include "ir/ts/tsInterfaceHeritage.h"
48 #include "ir/ts/tsInterfaceBody.h"
49 #include "ir/ts/tsFunctionType.h"
50 #include "ir/ts/tsQualifiedName.h"
51 #include "ir/module/importDefaultSpecifier.h"
52 #include "ir/module/importNamespaceSpecifier.h"
53 #include "ir/module/importDeclaration.h"
54 #include "ir/module/importSpecifier.h"
55 #include "ir/expressions/literals/stringLiteral.h"
56 #include "parser/program/program.h"
57 #include "util/helpers.h"
58 #include "util/ustring.h"
59 #include "checker/types/type.h"
60 #include "checker/types/ets/types.h"
61 
62 namespace panda::es2panda::varbinder {
63 
IdentifierAnalysis()64 void ETSBinder::IdentifierAnalysis()
65 {
66     ASSERT(Program()->Ast());
67     ASSERT(GetScope() == TopScope());
68     ASSERT(VarScope() == TopScope());
69 
70     recordTable_->SetProgram(Program());
71     globalRecordTable_.SetClassDefinition(Program()->GlobalClass());
72     externalRecordTable_.insert({Program(), &globalRecordTable_});
73 
74     BuildProgram();
75 
76     ASSERT(globalRecordTable_.ClassDefinition() == Program()->GlobalClass());
77 }
78 
LookupTypeArgumentReferences(ir::ETSTypeReference * typeRef)79 void ETSBinder::LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef)
80 {
81     auto *iter = typeRef->Part();
82 
83     while (iter != nullptr) {
84         if (iter->TypeParams() == nullptr) {
85             iter = iter->Previous();
86             continue;
87         }
88 
89         ResolveReferences(iter->TypeParams());
90         iter = iter->Previous();
91     }
92 }
93 
LookupTypeReference(ir::Identifier * ident,bool allowDynamicNamespaces)94 void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicNamespaces)
95 {
96     const auto &name = ident->Name();
97     auto *iter = GetScope();
98 
99     while (iter != nullptr) {
100         auto res = iter->Find(name, ResolveBindingOptions::DECLARATION | ResolveBindingOptions::TYPE_ALIASES);
101         if (res.variable == nullptr) {
102             break;
103         }
104 
105         if (IsDynamicModuleVariable(res.variable)) {
106             ident->SetVariable(res.variable);
107             return;
108         }
109 
110         if (allowDynamicNamespaces && IsDynamicNamespaceVariable(res.variable)) {
111             ident->SetVariable(res.variable);
112             return;
113         }
114 
115         switch (res.variable->Declaration()->Node()->Type()) {
116             case ir::AstNodeType::CLASS_DECLARATION:
117             case ir::AstNodeType::CLASS_DEFINITION:
118             case ir::AstNodeType::STRUCT_DECLARATION:
119             case ir::AstNodeType::TS_ENUM_DECLARATION:
120             case ir::AstNodeType::TS_INTERFACE_DECLARATION:
121             case ir::AstNodeType::TS_TYPE_PARAMETER:
122             case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
123             case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: {
124                 ident->SetVariable(res.variable);
125                 return;
126             }
127             default: {
128                 iter = iter->Parent();
129             }
130         }
131     }
132 
133     ThrowUnresolvableType(ident->Start(), name);
134 }
135 
ResolveReferencesForScope(ir::AstNode const * const parent,Scope * const scope)136 void ETSBinder::ResolveReferencesForScope(ir::AstNode const *const parent, Scope *const scope)
137 {
138     parent->Iterate([this, scope](auto *node) { ResolveReferenceForScope(node, scope); });
139 }
140 
ResolveReferenceForScope(ir::AstNode * const node,Scope * const scope)141 void ETSBinder::ResolveReferenceForScope(ir::AstNode *const node, Scope *const scope)
142 {
143     switch (node->Type()) {
144         case ir::AstNodeType::IDENTIFIER: {
145             auto *ident = node->AsIdentifier();
146             if (ident->Variable() != nullptr) {
147                 break;
148             }
149             if (auto const res = scope->Find(ident->Name(), ResolveBindingOptions::ALL); res.variable != nullptr) {
150                 ident->SetVariable(res.variable);
151             }
152             break;
153         }
154         case ir::AstNodeType::VARIABLE_DECLARATOR: {
155             auto scopeCtx = LexicalScope<Scope>::Enter(this, scope);
156             BuildVarDeclarator(node->AsVariableDeclarator());
157             break;
158         }
159         /* Maybe will be used
160         case ir::AstNodeType::BLOCK_STATEMENT: {
161             auto scope_ctx = LexicalScope<Scope>::Enter(this, node->AsBlockStatement()->Scope());
162             ResolveReferences(node);
163             break;
164         }
165         */
166         default: {
167             ResolveReferencesForScope(node, scope);
168             break;
169         }
170     }
171 }
172 
LookupIdentReference(ir::Identifier * ident)173 void ETSBinder::LookupIdentReference(ir::Identifier *ident)
174 {
175     const auto &name = ident->Name();
176     auto res = GetScope()->Find(name, ResolveBindingOptions::ALL);
177     if (res.level != 0) {
178         ASSERT(res.variable != nullptr);
179 
180         auto *outerFunction = GetScope()->EnclosingVariableScope()->Node();
181 
182         if ((!outerFunction->IsScriptFunction() || !outerFunction->AsScriptFunction()->IsArrow()) &&
183             !res.variable->IsGlobalVariable() && res.level > 1) {
184             ThrowInvalidCapture(ident->Start(), name);
185         }
186     }
187 
188     if (res.variable == nullptr) {
189         return;
190     }
191 
192     if (ident->IsReference() && res.variable->Declaration()->IsLetOrConstDecl() &&
193         !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
194         ThrowTDZ(ident->Start(), name);
195     }
196 }
197 
BuildClassProperty(const ir::ClassProperty * prop)198 void ETSBinder::BuildClassProperty(const ir::ClassProperty *prop)
199 {
200     ResolveReferences(prop);
201 }
202 
InitializeInterfaceIdent(ir::TSInterfaceDeclaration * decl)203 void ETSBinder::InitializeInterfaceIdent(ir::TSInterfaceDeclaration *decl)
204 {
205     auto res = GetScope()->Find(decl->Id()->Name());
206 
207     ASSERT(res.variable && res.variable->Declaration()->IsInterfaceDecl());
208     res.variable->AddFlag(VariableFlags::INITIALIZED);
209     decl->Id()->SetVariable(res.variable);
210 }
211 
ResolveEnumDeclaration(ir::TSEnumDeclaration * enumDecl)212 void ETSBinder::ResolveEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
213 {
214     auto enumScopeCtx = LexicalScope<LocalScope>::Enter(this, enumDecl->Scope());
215 
216     for (auto *member : enumDecl->Members()) {
217         ResolveReference(member);
218     }
219 }
220 
ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration * decl)221 void ETSBinder::ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration *decl)
222 {
223     auto boundCtx = BoundContext(recordTable_, decl);
224 
225     for (auto *extend : decl->Extends()) {
226         ResolveReference(extend);
227     }
228 
229     auto scopeCtx = LexicalScope<ClassScope>::Enter(this, decl->Scope()->AsClassScope());
230 
231     for (auto *stmt : decl->Body()->Body()) {
232         if (!stmt->IsClassProperty()) {
233             continue;
234         }
235 
236         ResolveReference(stmt);
237 
238         auto fieldVar =
239             ResolvePropertyReference(stmt->AsClassProperty(), decl->Scope()->AsClassScope())
240                 ->FindLocal(stmt->AsClassProperty()->Id()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
241         fieldVar->AddFlag(VariableFlags::INITIALIZED);
242     }
243 
244     for (auto *stmt : decl->Body()->Body()) {
245         if (stmt->IsClassProperty()) {
246             continue;
247         }
248         ResolveReference(stmt);
249     }
250 }
251 
BuildInterfaceDeclaration(ir::TSInterfaceDeclaration * decl)252 void ETSBinder::BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl)
253 {
254     if (decl->TypeParams() != nullptr) {
255         auto typeParamScopeCtx = LexicalScope<LocalScope>::Enter(this, decl->TypeParams()->Scope());
256         ResolveReferences(decl->TypeParams());
257         ResolveInterfaceDeclaration(decl);
258         return;
259     }
260 
261     ResolveInterfaceDeclaration(decl);
262 }
263 
BuildMethodDefinition(ir::MethodDefinition * methodDef)264 void ETSBinder::BuildMethodDefinition(ir::MethodDefinition *methodDef)
265 {
266     if (methodDef->Function()->TypeParams() != nullptr) {
267         auto scopeCtx = LexicalScope<LocalScope>::Enter(this, methodDef->Function()->TypeParams()->Scope());
268         ResolveReferences(methodDef->Function()->TypeParams());
269         ResolveMethodDefinition(methodDef);
270         return;
271     }
272 
273     ResolveMethodDefinition(methodDef);
274 }
275 
ResolveMethodDefinition(ir::MethodDefinition * methodDef)276 void ETSBinder::ResolveMethodDefinition(ir::MethodDefinition *methodDef)
277 {
278     auto *func = methodDef->Function();
279     ResolveReferences(methodDef);
280 
281     if (methodDef->IsStatic() || func->IsStaticBlock()) {
282         return;
283     }
284 
285     auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
286 
287     auto params = func->Scope()->ParamScope()->Params();
288     if (!params.empty() && params.front()->Name() == MANDATORY_PARAM_THIS) {
289         return;  // Implicit this parameter is already inserted by ResolveReferences(), don't insert it twice.
290     }
291 
292     auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
293     thisParam->Declaration()->BindNode(thisParam_);
294 }
295 
BuildMemberExpression(ir::MemberExpression * memberExpr)296 void ETSBinder::BuildMemberExpression(ir::MemberExpression *memberExpr)
297 {
298     ResolveReference(memberExpr->Object());
299 
300     if (memberExpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) {
301         ResolveReference(memberExpr->Property());
302     }
303 }
304 
BuildClassDefinition(ir::ClassDefinition * classDef)305 void ETSBinder::BuildClassDefinition(ir::ClassDefinition *classDef)
306 {
307     auto boundCtx = BoundContext(recordTable_, classDef);
308 
309     if (classDef->TypeParams() != nullptr) {
310         auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->TypeParams()->Scope());
311         ResolveReferences(classDef->TypeParams());
312         BuildClassDefinitionImpl(classDef);
313         return;
314     }
315 
316     BuildClassDefinitionImpl(classDef);
317 }
318 
ResolvePropertyReference(ir::ClassProperty * prop,ClassScope * scope)319 LocalScope *ETSBinder::ResolvePropertyReference(ir::ClassProperty *prop, ClassScope *scope)
320 {
321     ResolveReferences(prop);
322 
323     if (prop->IsStatic()) {
324         return scope->StaticFieldScope();
325     }
326 
327     return scope->InstanceFieldScope();
328 }
329 
BuildClassDefinitionImpl(ir::ClassDefinition * classDef)330 void ETSBinder::BuildClassDefinitionImpl(ir::ClassDefinition *classDef)
331 {
332     auto classCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope()->AsClassScope());
333 
334     if (classDef->Super() != nullptr) {
335         ResolveReference(classDef->Super());
336     }
337 
338     for (auto *impl : classDef->Implements()) {
339         ResolveReference(impl);
340     }
341 
342     for (auto *stmt : classDef->Body()) {
343         if (!stmt->IsClassProperty()) {
344             continue;
345         }
346 
347         auto fieldScope = ResolvePropertyReference(stmt->AsClassProperty(), classDef->Scope()->AsClassScope());
348         auto fieldName = stmt->AsClassProperty()->Id()->Name();
349         auto fieldVar = fieldScope->FindLocal(fieldName, varbinder::ResolveBindingOptions::BINDINGS);
350         fieldVar->AddFlag(VariableFlags::INITIALIZED);
351         if (fieldVar->Declaration()->IsConstDecl() && stmt->AsClassProperty()->Value() == nullptr) {
352             fieldVar->AddFlag(VariableFlags::EXPLICIT_INIT_REQUIRED);
353         }
354     }
355 
356     for (auto *stmt : classDef->Body()) {
357         if (stmt->IsClassProperty()) {
358             continue;
359         }
360         ResolveReference(stmt);
361     }
362 }
363 
AddLambdaFunctionThisParam(ir::ScriptFunction * func)364 void ETSBinder::AddLambdaFunctionThisParam(ir::ScriptFunction *func)
365 {
366     auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
367     auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
368     thisParam->Declaration()->BindNode(thisParam_);
369     if (!func->IsAsyncFunc()) {
370         Functions().push_back(func->Scope());
371     }
372 }
373 
AddInvokeFunctionThisParam(ir::ScriptFunction * func)374 void ETSBinder::AddInvokeFunctionThisParam(ir::ScriptFunction *func)
375 {
376     auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
377     auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
378     thisParam->Declaration()->BindNode(thisParam_);
379 }
380 
BuildProxyMethod(ir::ScriptFunction * func,const util::StringView & containingClassName,bool isStatic)381 void ETSBinder::BuildProxyMethod(ir::ScriptFunction *func, const util::StringView &containingClassName, bool isStatic)
382 {
383     ASSERT(!containingClassName.Empty());
384     func->Scope()->BindName(containingClassName);
385 
386     if (!isStatic) {
387         auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
388         auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
389         thisParam->Declaration()->BindNode(thisParam_);
390     }
391 
392     if (!func->IsAsyncFunc()) {
393         Functions().push_back(func->Scope());
394     }
395 }
396 
BuildLambdaObject(ir::AstNode * refNode,ir::ClassDefinition * lambdaObject,checker::Signature * signature)397 void ETSBinder::BuildLambdaObject(ir::AstNode *refNode, ir::ClassDefinition *lambdaObject,
398                                   checker::Signature *signature)
399 {
400     auto boundCtx = BoundContext(GetGlobalRecordTable(), lambdaObject);
401     const auto &lambdaBody = lambdaObject->Body();
402 
403     AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function());
404     AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function());
405 
406     LambdaObjects().insert({refNode, {lambdaObject, signature}});
407 }
408 
BuildFunctionType(ir::ETSFunctionType * funcType)409 void ETSBinder::BuildFunctionType(ir::ETSFunctionType *funcType)
410 {
411     auto boundCtx = BoundContext(GetGlobalRecordTable(), funcType->FunctionalInterface());
412 
413     auto *invokeFunc = funcType->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function();
414     auto *funcScope = invokeFunc->Scope();
415     funcScope->BindName(recordTable_->RecordName());
416     AddInvokeFunctionThisParam(invokeFunc);
417 
418     GetGlobalRecordTable()->Signatures().push_back(funcScope);
419 }
420 
AddDynamicSpecifiersToTopBindings(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import)421 void ETSBinder::AddDynamicSpecifiersToTopBindings(ir::AstNode *const specifier,
422                                                   const ir::ETSImportDeclaration *const import)
423 {
424     const auto name = [specifier]() {
425         if (specifier->IsImportNamespaceSpecifier()) {
426             return specifier->AsImportNamespaceSpecifier()->Local()->Name();
427         }
428 
429         return specifier->AsImportSpecifier()->Local()->Name();
430     }();
431 
432     auto *const decl = Allocator()->New<varbinder::LetDecl>(name, specifier);
433     auto *const var = Allocator()->New<varbinder::LocalVariable>(decl, varbinder::VariableFlags::STATIC);
434     var->AddFlag(VariableFlags::INITIALIZED);
435 
436     dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
437 
438     TopScope()->InsertDynamicBinding(name, var);
439 }
440 
InsertForeignBinding(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import,const util::StringView & name,Variable * var)441 void ETSBinder::InsertForeignBinding(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import,
442                                      const util::StringView &name, Variable *var)
443 {
444     if (import->Language().IsDynamic()) {
445         dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
446     }
447 
448     TopScope()->InsertForeignBinding(name, var);
449 }
450 
ImportAllForeignBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const parser::Program * const importProgram,const varbinder::GlobalScope * const importGlobalScope,const ir::ETSImportDeclaration * const import)451 void ETSBinder::ImportAllForeignBindings(ir::AstNode *const specifier,
452                                          const varbinder::Scope::VariableMap &globalBindings,
453                                          const parser::Program *const importProgram,
454                                          const varbinder::GlobalScope *const importGlobalScope,
455                                          const ir::ETSImportDeclaration *const import)
456 {
457     for (const auto [bindingName, var] : globalBindings) {
458         if (bindingName.Is(compiler::Signatures::ETS_GLOBAL)) {
459             const auto *const classDef = var->Declaration()->Node()->AsClassDeclaration()->Definition();
460             ImportGlobalProperties(classDef);
461             continue;
462         }
463 
464         if (!importGlobalScope->IsForeignBinding(bindingName) && !var->Declaration()->Node()->IsDefaultExported()) {
465             InsertForeignBinding(specifier, import, bindingName, var);
466         }
467     }
468 
469     for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticMethodScope()->Bindings()) {
470         if (!var->Declaration()->Node()->IsDefaultExported()) {
471             InsertForeignBinding(specifier, import, bindingName, var);
472         }
473     }
474 
475     for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticFieldScope()->Bindings()) {
476         if (!var->Declaration()->Node()->IsDefaultExported()) {
477             InsertForeignBinding(specifier, import, bindingName, var);
478         }
479     }
480 }
481 
AddImportNamespaceSpecifiersToTopBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const parser::Program * const importProgram,const varbinder::GlobalScope * const importGlobalScope,const ir::ETSImportDeclaration * const import)482 bool ETSBinder::AddImportNamespaceSpecifiersToTopBindings(ir::AstNode *const specifier,
483                                                           const varbinder::Scope::VariableMap &globalBindings,
484                                                           const parser::Program *const importProgram,
485                                                           const varbinder::GlobalScope *const importGlobalScope,
486                                                           const ir::ETSImportDeclaration *const import)
487 {
488     if (!specifier->IsImportNamespaceSpecifier()) {
489         return false;
490     }
491     const auto *const namespaceSpecifier = specifier->AsImportNamespaceSpecifier();
492 
493     if (namespaceSpecifier->Local()->Name().Empty()) {
494         ImportAllForeignBindings(specifier, globalBindings, importProgram, importGlobalScope, import);
495     }
496 
497     std::unordered_set<std::string> exportedNames;
498     for (auto item : ReExportImports()) {
499         if (auto source = import->ResolvedSource()->Str().Mutf8(),
500             program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.'));
501             source == program || (source + "/index") == program) {
502             // clang-format off
503             ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr(
504                                                         0, item->GetProgramPath().Mutf8().find_last_of('/'))),
505                                                     Allocator())
506                                             .View());
507             // clang-format on
508             dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start());
509 
510             for (auto it : item->GetETSImportDeclarations()->Specifiers()) {
511                 if (it->IsImportNamespaceSpecifier() &&
512                     !specifier->AsImportNamespaceSpecifier()->Local()->Name().Empty()) {
513                     std::cerr << "Warning: import with alias cannot be used with re-export\n";
514                     continue;
515                 }
516 
517                 AddSpecifiersToTopBindings(it, item->GetETSImportDeclarations(),
518                                            dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source()
519                                                                  : &dirName);
520                 if (it->IsImportSpecifier() &&
521                     !exportedNames.insert(it->AsImportSpecifier()->Local()->Name().Mutf8()).second) {
522                     ThrowError(import->Start(), "Ambiguous import \"" +
523                                                     it->AsImportSpecifier()->Local()->Name().Mutf8() +
524                                                     "\" has multiple matching exports");
525                 }
526             }
527         }
528     }
529 
530     return true;
531 }
532 
FindImportSpecifiersVariable(const util::StringView & imported,const varbinder::Scope::VariableMap & globalBindings,const ArenaVector<parser::Program * > & recordRes)533 Variable *ETSBinder::FindImportSpecifiersVariable(const util::StringView &imported,
534                                                   const varbinder::Scope::VariableMap &globalBindings,
535                                                   const ArenaVector<parser::Program *> &recordRes)
536 {
537     auto foundVar = globalBindings.find(imported);
538     if (foundVar == globalBindings.end()) {
539         const auto &staticMethodBindings = recordRes.front()->GlobalClassScope()->StaticMethodScope()->Bindings();
540         foundVar = staticMethodBindings.find(imported);
541         if (foundVar != staticMethodBindings.end()) {
542             return foundVar->second;
543         }
544         bool found = false;
545         for (auto res : recordRes) {
546             const auto &staticFieldBindings = res->GlobalClassScope()->StaticFieldScope()->Bindings();
547             foundVar = staticFieldBindings.find(imported);
548             if (foundVar != staticFieldBindings.end()) {
549                 found = true;
550                 foundVar->second->AsLocalVariable()->AddFlag(VariableFlags::INITIALIZED);
551                 break;
552             }
553         }
554         if (!found) {
555             return nullptr;
556         }
557     }
558 
559     return foundVar->second;
560 }
561 
AddImportSpecifiersToTopBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const ir::ETSImportDeclaration * const import,const ArenaVector<parser::Program * > & recordRes,std::vector<ir::ETSImportDeclaration * > viewedReExport)562 bool ETSBinder::AddImportSpecifiersToTopBindings(ir::AstNode *const specifier,
563                                                  const varbinder::Scope::VariableMap &globalBindings,
564                                                  const ir::ETSImportDeclaration *const import,
565                                                  const ArenaVector<parser::Program *> &recordRes,
566                                                  std::vector<ir::ETSImportDeclaration *> viewedReExport)
567 {
568     if (!specifier->IsImportSpecifier()) {
569         return false;
570     }
571     const ir::StringLiteral *const importPath = import->Source();
572     auto insertForeignBinding = [this, specifier, import](const util::StringView &name, Variable *var) {
573         if (import->Language().IsDynamic()) {
574             dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
575         }
576 
577         TopScope()->InsertForeignBinding(name, var);
578     };
579 
580     const auto *const importSpecifier = specifier->AsImportSpecifier();
581 
582     if (!importSpecifier->Imported()->IsIdentifier()) {
583         return true;
584     }
585 
586     const auto &imported = importSpecifier->Imported()->AsIdentifier()->Name();
587 
588     auto *const var = FindImportSpecifiersVariable(imported, globalBindings, recordRes);
589 
590     const auto &localName = [this, importSpecifier, &imported, &importPath]() {
591         if (importSpecifier->Local() != nullptr) {
592             auto fnc = [&importPath, &imported](const auto &savedSpecifier) {
593                 return importPath->Str() != savedSpecifier.first && imported == savedSpecifier.second;
594             };
595             if (!std::any_of(importSpecifiers_.begin(), importSpecifiers_.end(), fnc)) {
596                 TopScope()->EraseBinding(imported);
597             }
598 
599             importSpecifiers_.push_back(std::make_pair(importPath->Str(), imported));
600 
601             return importSpecifier->Local()->Name();
602         }
603 
604         return imported;
605     }();
606 
607     if (var == nullptr) {
608         for (auto item : ReExportImports()) {
609             if (auto source = import->ResolvedSource()->Str().Mutf8(),
610                 program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.'));
611                 source == program || (source + "/index") == program) {
612                 // clang-format off
613                 ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr(
614                                                             0, item->GetProgramPath().Mutf8().find_last_of('/'))),
615                                                         Allocator())
616                                             .View());
617                 // clang-format on
618                 dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start());
619 
620                 viewedReExport.push_back(item->GetETSImportDeclarations());
621                 AddSpecifiersToTopBindings(
622                     specifier, item->GetETSImportDeclarations(),
623                     dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source() : &dirName, viewedReExport);
624                 return true;
625             }
626         }
627         ThrowError(importPath->Start(), "Cannot find imported element " + imported.Mutf8());
628     }
629 
630     if (var->Declaration()->Node()->IsDefaultExported()) {
631         ThrowError(importPath->Start(), "Use the default import syntax to import a default exported element");
632     }
633 
634     insertForeignBinding(localName, var);
635     return true;
636 }
637 
FindStaticBinding(const ArenaVector<parser::Program * > & recordRes,const ir::StringLiteral * const importPath)638 varbinder::Variable *ETSBinder::FindStaticBinding(const ArenaVector<parser::Program *> &recordRes,
639                                                   const ir::StringLiteral *const importPath)
640 {
641     auto predicateFunc = [](const auto &item) { return item.second->Declaration()->Node()->IsDefaultExported(); };
642     const auto &staticMethodBindings = recordRes.front()->GlobalClassScope()->StaticMethodScope()->Bindings();
643     auto result = std::find_if(staticMethodBindings.begin(), staticMethodBindings.end(), predicateFunc);
644     if (result == staticMethodBindings.end()) {
645         const auto &staticFieldBindings = recordRes.front()->GlobalClassScope()->StaticFieldScope()->Bindings();
646         result = std::find_if(staticFieldBindings.begin(), staticFieldBindings.end(), predicateFunc);
647         if (result == staticFieldBindings.end()) {
648             ThrowError(importPath->Start(), "Cannot find default imported element in the target");
649         }
650     }
651     return result->second;
652 }
653 
GetExternalProgram(const util::StringView & sourceName,const ir::StringLiteral * importPath)654 ArenaVector<parser::Program *> ETSBinder::GetExternalProgram(const util::StringView &sourceName,
655                                                              const ir::StringLiteral *importPath)
656 {
657     const auto &extRecords = globalRecordTable_.Program()->ExternalSources();
658     auto recordRes = [this, extRecords, sourceName]() {
659         auto res = extRecords.find(sourceName);
660         if (res != extRecords.end()) {
661             return res;
662         }
663 
664         if (res = extRecords.find({sourceName.Mutf8() + "/index"}); res != extRecords.end()) {
665             return res;
666         }
667 
668         res = extRecords.find(GetResolvedImportPath(sourceName));
669         if (res == extRecords.end()) {
670             res = extRecords.find(GetResolvedImportPath({sourceName.Mutf8() + "/index"}));
671         }
672 
673         return res;
674     }();
675     if (recordRes == extRecords.end()) {
676         ThrowError(importPath->Start(), "Cannot find import: " + std::string(sourceName));
677     }
678 
679     ASSERT(!recordRes->second.empty());
680 
681     return recordRes->second;
682 }
683 
AddSpecifiersToTopBindings(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import,ir::StringLiteral * path,std::vector<ir::ETSImportDeclaration * > viewedReExport)684 void ETSBinder::AddSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import,
685                                            ir::StringLiteral *path,
686                                            std::vector<ir::ETSImportDeclaration *> viewedReExport)
687 {
688     const ir::StringLiteral *const importPath = path;
689 
690     if (import->IsPureDynamic()) {
691         AddDynamicSpecifiersToTopBindings(specifier, import);
692         return;
693     }
694 
695     const util::StringView sourceName = [import, importPath, this, &path]() {
696         if (import->Module() == nullptr) {
697             return importPath->Str();
698         }
699         char pathDelimiter = panda::os::file::File::GetPathDelim().at(0);
700         auto strImportPath = importPath->Str().Mutf8();
701         if (strImportPath.find(pathDelimiter) == (strImportPath.size() - 1)) {
702             return util::UString(strImportPath + import->Module()->Str().Mutf8(), Allocator()).View();
703         }
704 
705         std::string importFilePath;
706         if (!import->Source()->Str().Is(path->Str().Mutf8()) && !import->Source()->Str().Empty() &&
707             import->Source()->Str().Mutf8().substr(0, 1) == ".") {
708             importFilePath =
709                 import->Source()->Str().Mutf8().substr(import->Source()->Str().Mutf8().find_first_not_of('.'));
710             if (importFilePath.size() == 1) {
711                 importFilePath = "";
712             }
713         }
714 
715         return util::UString(strImportPath + importFilePath + pathDelimiter + import->Module()->Str().Mutf8(),
716                              Allocator())
717             .View();
718     }();
719 
720     auto record = GetExternalProgram(sourceName, importPath);
721     const auto *const importProgram = record.front();
722     const auto *const importGlobalScope = importProgram->GlobalScope();
723     const auto &globalBindings = importGlobalScope->Bindings();
724 
725     auto insertForeignBinding = [this, specifier, import](const util::StringView &name, Variable *var) {
726         if (import->Language().IsDynamic()) {
727             dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
728         }
729 
730         TopScope()->InsertForeignBinding(name, var);
731     };
732 
733     if (AddImportNamespaceSpecifiersToTopBindings(specifier, globalBindings, importProgram, importGlobalScope,
734                                                   import)) {
735         return;
736     }
737 
738     if (AddImportSpecifiersToTopBindings(specifier, globalBindings, import, record, std::move(viewedReExport))) {
739         return;
740     }
741 
742     ASSERT(specifier->IsImportDefaultSpecifier());
743     auto predicateFunc = [](const auto &item) { return item.second->Declaration()->Node()->IsDefaultExported(); };
744 
745     auto item = std::find_if(globalBindings.begin(), globalBindings.end(), predicateFunc);
746     if (item == globalBindings.end()) {
747         insertForeignBinding(specifier->AsImportDefaultSpecifier()->Local()->Name(),
748                              FindStaticBinding(record, importPath));
749         return;
750     }
751 
752     insertForeignBinding(specifier->AsImportDefaultSpecifier()->Local()->Name(), item->second);
753 }
754 
HandleCustomNodes(ir::AstNode * childNode)755 void ETSBinder::HandleCustomNodes(ir::AstNode *childNode)
756 {
757     switch (childNode->Type()) {
758         case ir::AstNodeType::ETS_TYPE_REFERENCE: {
759             auto *typeRef = childNode->AsETSTypeReference();
760             auto *baseName = typeRef->BaseName();
761             ASSERT(baseName->IsReference());
762             // We allow to resolve following types in pure dynamic mode:
763             // import * as I from "@dynamic"
764             // let x : I.X.Y
765             bool allowDynamicNamespaces = typeRef->Part()->Name() != baseName;
766             LookupTypeReference(baseName, allowDynamicNamespaces);
767             LookupTypeArgumentReferences(typeRef);
768             break;
769         }
770         case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
771             BuildInterfaceDeclaration(childNode->AsTSInterfaceDeclaration());
772             break;
773         }
774         case ir::AstNodeType::TS_ENUM_DECLARATION: {
775             ResolveEnumDeclaration(childNode->AsTSEnumDeclaration());
776             break;
777         }
778         case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
779             break;
780         }
781         case ir::AstNodeType::ETS_IMPORT_DECLARATION: {
782             BuildImportDeclaration(childNode->AsETSImportDeclaration());
783             break;
784         }
785         case ir::AstNodeType::MEMBER_EXPRESSION: {
786             BuildMemberExpression(childNode->AsMemberExpression());
787             break;
788         }
789         case ir::AstNodeType::METHOD_DEFINITION: {
790             BuildMethodDefinition(childNode->AsMethodDefinition());
791             break;
792         }
793         case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: {
794             BuildETSNewClassInstanceExpression(childNode->AsETSNewClassInstanceExpression());
795             break;
796         }
797         case ir::AstNodeType::ETS_FUNCTION_TYPE: {
798             BuildSignatureDeclarationBaseParams(childNode);
799             break;
800         }
801         default: {
802             ResolveReferences(childNode);
803             break;
804         }
805     }
806 }
807 
BuildInternalName(ir::ScriptFunction * scriptFunc)808 bool ETSBinder::BuildInternalName(ir::ScriptFunction *scriptFunc)
809 {
810     if (scriptFunc->IsArrow()) {
811         return true;
812     }
813 
814     auto *funcScope = scriptFunc->Scope();
815     funcScope->BindName(recordTable_->RecordName());
816     bool isExternal = recordTable_->IsExternal();
817 
818     bool compilable = scriptFunc->Body() != nullptr && !isExternal;
819     if (!compilable) {
820         recordTable_->Signatures().push_back(funcScope);
821     }
822 
823     if (isExternal) {
824         scriptFunc->AddFlag(ir::ScriptFunctionFlags::EXTERNAL);
825     }
826 
827     return compilable;
828 }
829 
AddCompilableFunction(ir::ScriptFunction * func)830 void ETSBinder::AddCompilableFunction(ir::ScriptFunction *func)
831 {
832     if (func->IsArrow() || func->IsAsyncFunc()) {
833         return;
834     }
835 
836     AddCompilableFunctionScope(func->Scope());
837 }
838 
BuildFunctionName(const ir::ScriptFunction * func) const839 void ETSBinder::BuildFunctionName(const ir::ScriptFunction *func) const
840 {
841     auto *funcScope = func->Scope();
842 
843     std::stringstream ss;
844     ASSERT(func->IsArrow() || !funcScope->Name().Empty());
845     ss << funcScope->Name() << compiler::Signatures::METHOD_SEPARATOR;
846 
847     const auto *signature = func->Signature();
848 
849     if (func->IsStaticBlock()) {
850         ss << compiler::Signatures::CCTOR;
851     } else if (func->IsConstructor()) {
852         ss << compiler::Signatures::CTOR;
853     } else {
854         if (func->IsGetter()) {
855             ss << compiler::Signatures::GETTER_BEGIN;
856         } else if (func->IsSetter()) {
857             ss << compiler::Signatures::SETTER_BEGIN;
858         }
859         ss << util::Helpers::FunctionName(Allocator(), func);
860     }
861 
862     signature->ToAssemblerType(GetCompilerContext(), ss);
863 
864     util::UString internalName(ss.str(), Allocator());
865     funcScope->BindInternalName(internalName.View());
866 }
867 
FormLambdaName(util::UString & name,const util::StringView & signature)868 void ETSBinder::FormLambdaName(util::UString &name, const util::StringView &signature)
869 {
870     name.Append(compiler::Signatures::LAMBDA_SEPARATOR);
871     auto replaced = std::string(signature.Utf8());
872     std::replace(replaced.begin(), replaced.end(), '.', '-');
873     std::replace(replaced.begin(), replaced.end(), ':', '-');
874     std::replace(replaced.begin(), replaced.end(), ';', '-');
875     replaced.append(std::to_string(0));
876     name.Append(replaced);
877 }
878 
FormFunctionalInterfaceName(util::UString & name,const util::StringView & signature)879 void ETSBinder::FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature)
880 {
881     auto replaced = std::string(signature.Utf8());
882     std::replace(replaced.begin(), replaced.end(), '.', '-');
883     std::replace(replaced.begin(), replaced.end(), ':', '-');
884     std::replace(replaced.begin(), replaced.end(), ';', '-');
885     replaced.append(std::to_string(0));
886     name.Append(replaced);
887 }
888 
BuildLambdaObjectName(const ir::AstNode * refNode)889 void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode)
890 {
891     auto found = lambdaObjects_.find(refNode);
892     ASSERT(found != lambdaObjects_.end());
893     auto *lambdaClass = found->second.first;
894     auto *signatureRef = found->second.second;
895 
896     util::UString lambdaObjectName(lambdaClass->Ident()->Name(), Allocator());
897     FormLambdaName(lambdaObjectName, signatureRef->InternalName());
898     lambdaClass->Ident()->SetName(lambdaObjectName.View());
899     lambdaClass->SetInternalName(lambdaClass->Ident()->Name());
900 
901     util::StringView assemblerName(lambdaClass->Ident()->Name());
902     auto *program = static_cast<const ir::ETSScript *>(refNode->GetTopStatement())->Program();
903     util::StringView prefix = program->GetPackageName();
904     if (!prefix.Empty()) {
905         util::UString fullPath(prefix, Allocator());
906         fullPath.Append('.');
907         fullPath.Append(assemblerName);
908         assemblerName = fullPath.View();
909     }
910 
911     checker::ETSObjectType *lambdaObject = lambdaClass->TsType()->AsETSObjectType();
912     lambdaObject->SetName(lambdaClass->Ident()->Name());
913     lambdaObject->SetAssemblerName(lambdaClass->Ident()->Name());
914 
915     const auto &lambdaBody = lambdaClass->Body();
916     auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function();
917     auto *ctorFuncScope = ctorFunc->Scope();
918     ctorFuncScope->BindName(lambdaClass->Ident()->Name());
919 
920     auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function();
921     auto *invokeFuncScope = invokeFunc->Scope();
922     invokeFuncScope->BindName(lambdaClass->Ident()->Name());
923 }
924 
BuildFunctionalInterfaceName(ir::ETSFunctionType * funcType)925 void ETSBinder::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType)
926 {
927     auto *functionalInterface = funcType->FunctionalInterface();
928     auto *invokeFunc = functionalInterface->Body()->Body()[0]->AsMethodDefinition()->Function();
929     util::UString functionalInterfaceName(functionalInterface->Id()->Name(), Allocator());
930     std::stringstream ss;
931     invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), ss);
932     std::string signatureString = ss.str();
933     util::StringView signatureName(signatureString);
934     FormFunctionalInterfaceName(functionalInterfaceName, signatureName);
935     functionalInterface->Id()->SetName(functionalInterfaceName.View());
936     util::UString internalName(Program()->GetPackageName(), Allocator());
937     if (!(internalName.View().Empty())) {
938         internalName.Append(compiler::Signatures::METHOD_SEPARATOR);
939     }
940     internalName.Append(functionalInterface->Id()->Name());
941     functionalInterface->SetInternalName(internalName.View());
942 
943     checker::ETSObjectType *functionalInterfaceType = functionalInterface->TsType()->AsETSObjectType();
944     functionalInterfaceType->SetName(functionalInterface->Id()->Name());
945     functionalInterfaceType->SetAssemblerName(internalName.View());
946 
947     auto *invokeFuncScope = invokeFunc->Scope();
948     invokeFuncScope->BindName(functionalInterface->Id()->Name());
949 
950     util::UString invokeInternalName(Program()->GetPackageName(), Allocator());
951     if (!(invokeInternalName.View().Empty())) {
952         invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR);
953     }
954     invokeInternalName.Append(invokeFuncScope->Name());
955     invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR);
956     invokeInternalName.Append(invokeFunc->Id()->Name());
957     std::stringstream invokeSignatureSs;
958     invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), invokeSignatureSs);
959     invokeInternalName.Append(invokeSignatureSs.str());
960     invokeFuncScope->BindInternalName(invokeInternalName.View());
961 }
962 
InitImplicitThisParam()963 void ETSBinder::InitImplicitThisParam()
964 {
965     thisParam_ = Allocator()->New<ir::Identifier>("this", Allocator());
966 }
967 
BuildProgram()968 void ETSBinder::BuildProgram()
969 {
970     for (auto &[_, extPrograms] : Program()->ExternalSources()) {
971         (void)_;
972         for (auto *extProg : extPrograms) {
973             BuildExternalProgram(extProg);
974         }
975     }
976 
977     for (auto *defaultImport : defaultImports_) {
978         BuildImportDeclaration(defaultImport);
979     }
980 
981     auto &stmts = Program()->Ast()->Statements();
982     const auto etsGlobal = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) {
983         return stmt->IsClassDeclaration() &&
984                stmt->AsClassDeclaration()->Definition()->Ident()->Name().Is(compiler::Signatures::ETS_GLOBAL);
985     });
986     if (etsGlobal != stmts.end()) {
987         const auto begin = std::find_if(stmts.rbegin(), stmts.rend(), [](const ir::Statement *stmt) {
988                                return stmt->IsETSImportDeclaration() || stmt->IsETSPackageDeclaration();
989                            }).base();
990 
991         const size_t index = std::distance(begin, etsGlobal);
992         std::rotate(begin, begin + index, begin + index + 1);
993     }
994 
995     for (auto *stmt : stmts) {
996         ResolveReference(stmt);
997     }
998 }
999 
BuildExternalProgram(parser::Program * extProgram)1000 void ETSBinder::BuildExternalProgram(parser::Program *extProgram)
1001 {
1002     auto *savedProgram = Program();
1003     auto *savedRecordTable = recordTable_;
1004     auto *savedTopScope = TopScope();
1005 
1006     auto flags = Program()->VarBinder()->IsGenStdLib() ? RecordTableFlags::NONE : RecordTableFlags::EXTERNAL;
1007     auto *extRecordTable = Allocator()->New<RecordTable>(Allocator(), extProgram, flags);
1008     externalRecordTable_.insert({extProgram, extRecordTable});
1009 
1010     ResetTopScope(extProgram->GlobalScope());
1011     recordTable_ = extRecordTable;
1012     SetProgram(extProgram);
1013 
1014     BuildProgram();
1015 
1016     SetProgram(savedProgram);
1017     recordTable_ = savedRecordTable;
1018     ResetTopScope(savedTopScope);
1019 }
1020 
BuildETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression * classInstance)1021 void ETSBinder::BuildETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *classInstance)
1022 {
1023     BoundContext boundCtx(recordTable_, classInstance->ClassDefinition());
1024     ResolveReference(classInstance->GetTypeRef());
1025 
1026     for (auto *arg : classInstance->GetArguments()) {
1027         ResolveReference(arg);
1028     }
1029 
1030     if (classInstance->ClassDefinition() == nullptr) {
1031         return;
1032     }
1033 
1034     ResolveReference(classInstance->ClassDefinition());
1035 }
1036 
BuildImportDeclaration(ir::ETSImportDeclaration * decl)1037 void ETSBinder::BuildImportDeclaration(ir::ETSImportDeclaration *decl)
1038 {
1039     if (decl->Source()->Str() == Program()->AbsoluteName()) {
1040         return;
1041     }
1042 
1043     auto specifiers = decl->Specifiers();
1044 
1045     for (auto specifier : specifiers) {
1046         AddSpecifiersToTopBindings(specifier, decl, decl->Source());
1047     }
1048 }
1049 
ImportGlobalPropertiesForNotDefaultedExports(varbinder::Variable * var,const util::StringView & name,const ir::ClassElement * classElement)1050 bool ETSBinder::ImportGlobalPropertiesForNotDefaultedExports(varbinder::Variable *var, const util::StringView &name,
1051                                                              const ir::ClassElement *classElement)
1052 {
1053     if (var->Declaration()->Node()->IsDefaultExported()) {
1054         return false;
1055     }
1056 
1057     const auto insRes = TopScope()->InsertForeignBinding(name, var);
1058     if (!(!insRes.second && insRes.first != TopScope()->Bindings().end()) || !(insRes.first->second != var)) {
1059         return true;
1060     }
1061     if (insRes.first->second->Declaration()->IsFunctionDecl() && var->Declaration()->IsFunctionDecl()) {
1062         auto *const currentNode = insRes.first->second->Declaration()->Node();
1063         auto *const method = var->Declaration()->Node()->AsMethodDefinition();
1064         if (!currentNode->AsMethodDefinition()->HasOverload(method)) {
1065             currentNode->AsMethodDefinition()->AddOverload(method);
1066             method->Function()->Id()->SetVariable(insRes.first->second);
1067             method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
1068         }
1069         return true;
1070     }
1071 
1072     auto str = util::Helpers::AppendAll("Variable '", name.Utf8(), "'");
1073     if (insRes.first->second->Declaration()->Type() == var->Declaration()->Type()) {
1074         str += " is already defined.";
1075     } else {
1076         str += " is already defined with different type.";
1077     }
1078     ThrowError(classElement->Id()->Start(), str);
1079 }
1080 
ImportGlobalProperties(const ir::ClassDefinition * const classDef)1081 void ETSBinder::ImportGlobalProperties(const ir::ClassDefinition *const classDef)
1082 {
1083     const auto scopeCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope()->AsClassScope());
1084 
1085     for (const auto *const prop : classDef->Body()) {
1086         const auto *const classElement = prop->AsClassElement();
1087 
1088         if (classElement->IsClassStaticBlock()) {
1089             continue;
1090         }
1091 
1092         ASSERT(classElement->IsStatic());
1093         const auto &name = classElement->Id()->Name();
1094         auto *const var = scopeCtx.GetScope()->FindLocal(name, ResolveBindingOptions::ALL);
1095         ASSERT(var != nullptr);
1096 
1097         if (ImportGlobalPropertiesForNotDefaultedExports(var, name, classElement)) {
1098             return;
1099         }
1100     }
1101 }
1102 
DynamicImportDataForVar(const Variable * var) const1103 const DynamicImportData *ETSBinder::DynamicImportDataForVar(const Variable *var) const
1104 {
1105     auto it = dynamicImportVars_.find(var);
1106     if (it == dynamicImportVars_.cend()) {
1107         return nullptr;
1108     }
1109 
1110     return &it->second;
1111 }
1112 
IsDynamicModuleVariable(const Variable * var) const1113 bool ETSBinder::IsDynamicModuleVariable(const Variable *var) const
1114 {
1115     auto *data = DynamicImportDataForVar(var);
1116     if (data == nullptr) {
1117         return false;
1118     }
1119 
1120     return data->specifier->IsImportSpecifier();
1121 }
1122 
IsDynamicNamespaceVariable(const Variable * var) const1123 bool ETSBinder::IsDynamicNamespaceVariable(const Variable *var) const
1124 {
1125     auto *data = DynamicImportDataForVar(var);
1126     if (data == nullptr) {
1127         return false;
1128     }
1129 
1130     return data->specifier->IsImportNamespaceSpecifier();
1131 }
1132 
1133 }  // namespace panda::es2panda::varbinder
1134