• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 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 #ifndef ES2PANDA_COMPILER_SCOPES_SCOPE_H
17 #define ES2PANDA_COMPILER_SCOPES_SCOPE_H
18 
19 #include <binder/declaration.h>
20 #include <binder/variable.h>
21 #include <parser/program/program.h>
22 #include <util/enumbitops.h>
23 #include <util/ustring.h>
24 
25 #include <map>
26 #include <unordered_map>
27 #include <vector>
28 
29 namespace panda::es2panda::compiler {
30 class IRNode;
31 } // namespace panda::es2panda::compiler
32 
33 namespace panda::es2panda::ir {
34 class ScriptFunction;
35 class Statement;
36 } // namespace panda::es2panda::ir
37 
38 namespace panda::es2panda::parser {
39 class Program;
40 } // namespace panda::es2panda::parser
41 
42 namespace panda::es2panda::binder {
43 
44 #define DECLARE_CLASSES(type, className) class className;
45 SCOPE_TYPES(DECLARE_CLASSES)
46 #undef DECLARE_CLASSES
47 
48 class Scope;
49 class VariableScope;
50 class Variable;
51 
52 using VariableMap = ArenaMap<util::StringView, Variable *>;
53 
54 class TSBindings {
55 public:
TSBindings(ArenaAllocator * allocator)56     explicit TSBindings(ArenaAllocator *allocator) : allocator_(allocator) {}
57 
58     template <TSBindingType type>
AddTSVariable(const util::StringView & name,Variable * variable)59     bool AddTSVariable(const util::StringView &name, Variable *variable)
60     {
61         static_assert(type < TSBindingType::COUNT);
62         size_t index = GetIndex(type);
63         if (tsBindings_[index] == nullptr) {
64             tsBindings_[index] = allocator_->New<VariableMap>(allocator_->Adapter());
65         }
66         return tsBindings_[index]->insert({name, variable}).second;
67     }
68 
69     template <TSBindingType type>
FindTSVariable(const util::StringView & name)70     Variable *FindTSVariable(const util::StringView &name) const
71     {
72         static_assert(type < TSBindingType::COUNT);
73         size_t index = GetIndex(type);
74         if (tsBindings_[index] == nullptr) {
75             return nullptr;
76         }
77         auto res = tsBindings_[index]->find(name);
78         if (res == tsBindings_[index]->end()) {
79             return nullptr;
80         }
81         return res->second;
82     }
83 
InTSBindings(const util::StringView & name)84     bool InTSBindings(const util::StringView &name) const
85     {
86         for (size_t i = 0; i < GetIndex(TSBindingType::COUNT); i++) {
87             if (tsBindings_[i] && tsBindings_[i]->find(name) != tsBindings_[i]->end()) {
88                 return true;
89             }
90         }
91         return false;
92     }
93 
94 private:
GetIndex(TSBindingType type)95     size_t GetIndex(TSBindingType type) const
96     {
97         return static_cast<size_t>(type);
98     }
99 
100     ArenaAllocator *allocator_;
101     std::array<VariableMap *, static_cast<size_t>(TSBindingType::COUNT)> tsBindings_ {};
102 };
103 
104 class ExportBindings {
105 public:
ExportBindings(ArenaAllocator * allocator)106     explicit ExportBindings(ArenaAllocator *allocator)
107         : exportBindings_(allocator->Adapter()),
108           exportTSBindings_(allocator)
109     {
110     }
111 
FindExportVariable(const util::StringView & name)112     Variable *FindExportVariable(const util::StringView &name) const
113     {
114         auto res = exportBindings_.find(name);
115         if (res == exportBindings_.end()) {
116             return nullptr;
117         }
118         return res->second;
119     }
120 
AddExportVariable(const util::StringView & name,Variable * var)121     bool AddExportVariable(const util::StringView &name, Variable *var)
122     {
123         return exportBindings_.insert({name, var}).second;
124     }
125 
InExportBindings(const util::StringView & name)126     bool InExportBindings(const util::StringView &name) const
127     {
128         auto res = FindExportVariable(name);
129         return res != nullptr || exportTSBindings_.InTSBindings(name);
130     }
131 
132     template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)133     Variable *FindExportTSVariable(const util::StringView &name) const
134     {
135         return exportTSBindings_.FindTSVariable<type>(name);
136     }
137 
138     template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)139     bool AddExportTSVariable(const util::StringView &name, Variable *var)
140     {
141         return exportTSBindings_.AddTSVariable<type>(name, var);
142     }
143 
144 private:
145     VariableMap exportBindings_;
146     TSBindings exportTSBindings_;
147 };
148 
149 class ScopeFindResult {
150 public:
151     ScopeFindResult() = default;
ScopeFindResult(util::StringView n,Scope * s,uint32_t l,Variable * v)152     ScopeFindResult(util::StringView n, Scope *s, uint32_t l, Variable *v)
153         : ScopeFindResult(n, s, l, l, l, v, nullptr)
154     {
155     }
ScopeFindResult(Scope * s,uint32_t l,uint32_t ll,Variable * v)156     ScopeFindResult(Scope *s, uint32_t l, uint32_t ll, Variable *v) : scope(s), level(l), lexLevel(ll), variable(v) {}
ScopeFindResult(util::StringView n,Scope * s,uint32_t l,uint32_t ll,uint32_t sl,Variable * v,ir::ScriptFunction * c)157     ScopeFindResult(util::StringView n, Scope *s, uint32_t l, uint32_t ll, uint32_t sl,
158                     Variable *v, ir::ScriptFunction *c)
159         : name(n), scope(s), level(l), lexLevel(ll), sendableLevel(sl), variable(v), concurrentFunc(c)
160     {
161     }
162 
163     util::StringView name {};
164     Scope *scope {};
165     uint32_t level {};
166     uint32_t lexLevel {};
167     uint32_t sendableLevel {};
168     Variable *variable {};
169     ir::ScriptFunction *concurrentFunc {};
170 };
171 
172 class Result {
173 public:
174     uint32_t slot;
175     bool isMethod;
176     bool isStatic;
177     bool isGetter;
178     bool isSetter;
179     uint32_t validateMethodSlot;
180 };
181 
182 class PrivateNameFindResult {
183 public:
184     int32_t lexLevel;
185     Result result;
186 };
187 
188 
189 class Scope {
190 public:
191     virtual ~Scope() = default;
192     NO_COPY_SEMANTIC(Scope);
193     NO_MOVE_SEMANTIC(Scope);
194 
195     virtual ScopeType Type() const = 0;
196 
197 #define DECLARE_CHECKS_CASTS(scopeType, className)        \
198     bool Is##className() const                            \
199     {                                                     \
200         return Type() == ScopeType::scopeType;            \
201     }                                                     \
202     className *As##className()                            \
203     {                                                     \
204         ASSERT(Is##className());                          \
205         return reinterpret_cast<className *>(this);       \
206     }                                                     \
207     const className *As##className() const                \
208     {                                                     \
209         ASSERT(Is##className());                          \
210         return reinterpret_cast<const className *>(this); \
211     }
SCOPE_TYPES(DECLARE_CHECKS_CASTS)212     SCOPE_TYPES(DECLARE_CHECKS_CASTS)
213 #undef DECLARE_CHECKS_CASTS
214 
215     virtual bool IsVariableScope() const
216     {
217         return Type() > ScopeType::LOCAL;
218     }
219 
IsFunctionVariableScope()220     bool IsFunctionVariableScope() const
221     {
222         return Type() >= ScopeType::FUNCTION;
223     }
224 
AsFunctionVariableScope()225     FunctionScope *AsFunctionVariableScope()
226     {
227         ASSERT(IsFunctionVariableScope());
228         return reinterpret_cast<FunctionScope *>(this);
229     }
230 
AsFunctionVariableScope()231     const FunctionScope *AsFunctionVariableScope() const
232     {
233         ASSERT(IsFunctionVariableScope());
234         return reinterpret_cast<const FunctionScope *>(this);
235     }
236 
AsVariableScope()237     VariableScope *AsVariableScope()
238     {
239         ASSERT(IsVariableScope());
240         return reinterpret_cast<VariableScope *>(this);
241     }
242 
AsVariableScope()243     const VariableScope *AsVariableScope() const
244     {
245         ASSERT(IsVariableScope());
246         return reinterpret_cast<const VariableScope *>(this);
247     }
248 
249     VariableScope *EnclosingVariableScope();
250 
251     FunctionScope *EnclosingFunctionVariableScope();
252 
Decls()253     const ArenaVector<Decl *> &Decls() const
254     {
255         return decls_;
256     }
257 
Parent()258     Scope *Parent()
259     {
260         return parent_;
261     }
262 
Parent()263     const Scope *Parent() const
264     {
265         return parent_;
266     }
267 
SetParent(Scope * parent)268     void SetParent(Scope *parent)
269     {
270         parent_ = parent;
271         SetTopScope();
272     }
273 
ScopeStart()274     const compiler::IRNode *ScopeStart() const
275     {
276         return startIns_;
277     }
278 
ScopeEnd()279     const compiler::IRNode *ScopeEnd() const
280     {
281         return endIns_;
282     }
283 
SetScopeStart(const compiler::IRNode * ins)284     void SetScopeStart(const compiler::IRNode *ins)
285     {
286         startIns_ = ins;
287     }
288 
SetScopeEnd(const compiler::IRNode * ins)289     void SetScopeEnd(const compiler::IRNode *ins)
290     {
291         endIns_ = ins;
292     }
293 
Node()294     const ir::AstNode *Node() const
295     {
296         return node_;
297     }
298 
Node()299     ir::AstNode *Node()
300     {
301         return node_;
302     }
303 
BindNode(ir::AstNode * node)304     void BindNode(ir::AstNode *node)
305     {
306         node_ = node;
307     }
308 
AddDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)309     bool AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
310     {
311         CHECK_NOT_NULL(decl);
312         decls_.push_back(decl);
313         return AddBinding(allocator, FindLocal(decl->Name()), decl, extension);
314     }
315 
AddTsDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)316     bool AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
317     {
318         decls_.push_back(decl);
319         return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension);
320     }
321 
HasParamScope()322     virtual bool HasParamScope()
323     {
324         return false;
325     }
326 
327     template <typename T, typename... Args>
328     T *NewDecl(ArenaAllocator *allocator, Args &&... args);
329 
330     template <typename DeclType, typename VariableType>
331     VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags);
332 
333     template <typename DeclType = binder::LetDecl, typename VariableType = binder::LocalVariable>
334     static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
335                                    const ir::AstNode *node);
336 
337     template <typename T, typename... Args>
338     void PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args);
339 
Bindings()340     VariableMap &Bindings()
341     {
342         return bindings_;
343     }
344 
Bindings()345     const VariableMap &Bindings() const
346     {
347         return bindings_;
348     }
349 
350     virtual bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
351                             [[maybe_unused]] ScriptExtension extension) = 0;
352 
353     Variable *FindLocal(const util::StringView &name,
354                         ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
355 
356     ScopeFindResult Find(const util::StringView &name,
357                          ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
358 
359     std::pair<uint32_t, uint32_t> Find(const ir::Expression *expr, bool onlyLevel = false) const;
360 
361     PrivateNameFindResult FindPrivateName(const util::StringView &name, bool isSetter = false) const;
362 
363     Decl *FindDecl(const util::StringView &name) const;
364 
365     bool HasVarDecl(const util::StringView &name) const;
366 
367     void CalculateLevelInCorrespondingFunctionScope(const FunctionParamScope *scope, uint32_t &lexLevel,
368                                                     uint32_t &sendableLevel) const;
369 
370     template <TSBindingType type>
FindLocalTSVariable(const util::StringView & name)371     Variable *FindLocalTSVariable(const util::StringView &name) const
372     {
373         return tsBindings_.FindTSVariable<type>(name);
374     }
375 
376     template <TSBindingType type>
AddLocalTSVariable(const util::StringView & name,Variable * var)377     void AddLocalTSVariable(const util::StringView &name, Variable *var)
378     {
379         tsBindings_.AddTSVariable<type>(name, var);
380     }
381 
InLocalTSBindings(const util::StringView & name)382     bool InLocalTSBindings(const util::StringView &name) const
383     {
384         return tsBindings_.InTSBindings(name);
385     }
386 
GetFullScopeName()387     virtual const util::StringView &GetFullScopeName()
388     {
389         // Most scopes have no scopeName therefore their fullScopeNames should be got from their parents
390         if (parent_) {
391             return parent_->GetFullScopeName();
392         }
393         return fullScopeName_;
394     }
395 
GetDuplicateScopeIndex(const util::StringView & childScopeName)396     virtual uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName)
397     {
398         // Most sub class has no scope name, so as duplicate index, need to get from parent.
399         if (parent_) {
400             return parent_->GetDuplicateScopeIndex(childScopeName);
401         }
402 
403         return 0;
404     }
405 
SetSelfScopeName(const util::StringView & ident)406     virtual void SetSelfScopeName(const util::StringView &ident)
407     {
408         if (hasSelfScopeNameSet_) {
409             return;
410         }
411         hasSelfScopeNameSet_ = true;
412 
413         if (!util::Helpers::IsSpecialScopeName(ident)) {
414             selfScopeName_ = ident;
415         }
416 
417         Scope *parent = GetParentWithScopeName();
418         if (parent != nullptr) {
419             std::stringstream selfScopeName;
420             selfScopeName << GetScopeTag() << selfScopeName_;
421             scopeDuplicateIndex_ = parent->GetDuplicateScopeIndex(
422                 util::UString(selfScopeName.str(), allocator_).View());
423         }
424     }
425 
GetScopeNames()426     ArenaUnorderedMap<util::StringView, int32_t> &GetScopeNames()
427     {
428         return topScope_->scopeNames_;
429     }
430 
431 protected:
Scope(ArenaAllocator * allocator,Scope * parent)432     explicit Scope(ArenaAllocator *allocator, Scope *parent)
433         : parent_(parent),
434           decls_(allocator->Adapter()),
435           bindings_(allocator->Adapter()),
436           tsBindings_(allocator),
437           scopesIndex_(allocator->Adapter()),
438           scopeNames_(allocator->Adapter()),
439           allocator_(allocator)
440     {
441         SetTopScope();
442     }
443 
444     /**
445      * @return true - if the variable is shadowed
446      *         false - otherwise
447      */
448     using VariableVisitior = std::function<bool(const Variable *)>;
449 
450     /**
451      * @return true - if the variable is shadowed
452      *         false - otherwise
453      */
454     std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor);
455 
456     bool AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
457                   [[maybe_unused]] ScriptExtension extension);
458 
459     void SetFullScopeNames();
460 
SetTopScope()461     void SetTopScope()
462     {
463         if (parent_) {
464             topScope_ = parent_->GetTopScope();
465         } else {
466             topScope_ = this;
467         }
468     }
469 
470     void OptimizeSelfScopeName(std::stringstream &selfScopeStream);
471 
GetParentWithScopeName()472     virtual Scope *GetParentWithScopeName()
473     {
474         return parent_;
475     }
476 
GetSelfScopeName()477     virtual util::StringView GetSelfScopeName()
478     {
479         if (hasSelfScopeNameSet_) {
480             return selfScopeName_;
481         }
482 
483         std::stringstream scopeName;
484 
485         if (scopeDuplicateIndex_ > 0) {
486             scopeName << util::Helpers::DUPLICATED_SEPERATOR <<
487                          std::hex << scopeDuplicateIndex_;
488         }
489 
490         return util::UString(scopeName.str(), allocator_).View();
491     }
492 
GetTopScope()493     Scope *GetTopScope()
494     {
495         return topScope_;
496     }
497 
498     Scope *parent_ {};
499     Scope *topScope_ {};
500     ArenaVector<Decl *> decls_;
501     VariableMap bindings_;
502     TSBindings tsBindings_;
503     ir::AstNode *node_ {};
504     const compiler::IRNode *startIns_ {};
505     const compiler::IRNode *endIns_ {};
506     ArenaUnorderedMap<util::StringView, uint32_t> scopesIndex_;
507     ArenaUnorderedMap<util::StringView, int32_t> scopeNames_;
508     util::StringView fullScopeName_ {};
509     ArenaAllocator *allocator_ {};
510     uint32_t scopeDuplicateIndex_ = 0;
511     util::StringView selfScopeName_ {};
512     bool hasSelfScopeNameSet_ { false };
513     bool hasFullScopeNameSet_ { false };
514 
515 private:
GetScopeTag()516     virtual util::StringView GetScopeTag()
517     {
518         return util::UString(util::Helpers::STRING_EMPTY.data(), allocator_).View();
519     }
520 };
521 
522 class VariableScope : public Scope {
523 public:
524     ~VariableScope() override = default;
525     NO_COPY_SEMANTIC(VariableScope);
526     NO_MOVE_SEMANTIC(VariableScope);
527 
AddFlag(VariableScopeFlags flag)528     void AddFlag(VariableScopeFlags flag)
529     {
530         flags_ |= flag;
531     }
532 
ClearFlag(VariableScopeFlags flag)533     void ClearFlag(VariableScopeFlags flag)
534     {
535         flags_ &= ~flag;
536     }
537 
HasFlag(VariableScopeFlags flag)538     bool HasFlag(VariableScopeFlags flag) const
539     {
540         return (flags_ & flag) != 0;
541     }
542 
RestoreFuncMain0LexEnv(uint32_t slotSize)543     void RestoreFuncMain0LexEnv(uint32_t slotSize)
544     {
545         slotIndex_ = slotSize;
546     }
547 
NextSlot()548     uint32_t NextSlot()
549     {
550         return slotIndex_++;
551     }
552 
NextSendableSlot()553     uint32_t NextSendableSlot()
554     {
555         return sendableSlotIndex_++;
556     }
557 
LexicalSlots()558     uint32_t LexicalSlots() const
559     {
560         return slotIndex_;
561     }
562 
SendableSlots()563     uint32_t SendableSlots() const
564     {
565         return sendableSlotIndex_;
566     }
567 
NeedLexEnv()568     bool NeedLexEnv() const
569     {
570         return slotIndex_ != 0;
571     }
572 
NeedSendableEnv()573     bool NeedSendableEnv() const
574     {
575         return sendableSlotIndex_ != 0;
576     }
577 
AddLexicalVarNameAndType(uint32_t slot,util::StringView name,int type)578     void AddLexicalVarNameAndType(uint32_t slot, util::StringView name, int type)
579     {
580         lexicalVarNameAndTypes_.emplace(slot, std::pair<util::StringView, int>(name, type));
581     }
582 
GetLexicalVarNameAndTypes()583     ArenaMap<uint32_t, std::pair<util::StringView, int>> &GetLexicalVarNameAndTypes()
584     {
585         return lexicalVarNameAndTypes_;
586     }
587 
588 protected:
VariableScope(ArenaAllocator * allocator,Scope * parent)589     explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent),
590                                                                        lexicalVarNameAndTypes_(allocator->Adapter()) {}
591 
592     inline VariableFlags DeclFlagToVariableFlag(DeclarationFlags declFlag);
593 
594     template <typename T>
595     bool AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
596 
597     template <typename T>
598     bool AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
599                      [[maybe_unused]] ScriptExtension extension);
600 
601     template <typename T>
602     bool AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
603 
604     template <typename T>
605     bool AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
606 
607     template <typename T>
608     bool AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags);
609 
610     template <typename T>
611     bool AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
612 
613     VariableScopeFlags flags_ {};
614     uint32_t slotIndex_ {};
615     uint32_t sendableSlotIndex_ {};
616     ArenaMap<uint32_t, std::pair<util::StringView, int>> lexicalVarNameAndTypes_; // for debuginfo and patchFix
617 };
618 
619 class ParamScope : public Scope {
620 public:
Type()621     ScopeType Type() const override
622     {
623         return ScopeType::PARAM;
624     }
625 
Params()626     ArenaVector<LocalVariable *> &Params()
627     {
628         return params_;
629     }
630 
Params()631     const ArenaVector<LocalVariable *> &Params() const
632     {
633         return params_;
634     }
635 
HasParam(util::StringView name)636     bool HasParam(util::StringView name) const
637     {
638         for (auto *param : params_) {
639             if (param->Name() == name) {
640                 return true;
641             }
642         }
643 
644         return false;
645     }
646 
647     std::tuple<ParameterDecl *, const ir::AstNode *> AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param);
648 
649 protected:
ParamScope(ArenaAllocator * allocator,Scope * parent)650     explicit ParamScope(ArenaAllocator *allocator, Scope *parent)
651         : Scope(allocator, parent), params_(allocator->Adapter())
652     {
653     }
654 
655     bool AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
656 
657     ArenaVector<LocalVariable *> params_;
658 };
659 
660 class FunctionScope;
661 
662 class FunctionParamScope : public ParamScope {
663 public:
FunctionParamScope(ArenaAllocator * allocator,Scope * parent)664     explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
665 
GetFunctionScope()666     FunctionScope *GetFunctionScope() const
667     {
668         return functionScope_;
669     }
670 
BindFunctionScope(FunctionScope * funcScope)671     void BindFunctionScope(FunctionScope *funcScope)
672     {
673         functionScope_ = funcScope;
674     }
675 
NameVar()676     LocalVariable *NameVar() const
677     {
678         return nameVar_;
679     }
680 
681     void BindName(ArenaAllocator *allocator, util::StringView name);
682 
Type()683     ScopeType Type() const override
684     {
685         return ScopeType::FUNCTION_PARAM;
686     }
687 
688     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
689                     [[maybe_unused]] ScriptExtension extension) override;
690 
RemoveThisParam(const std::string_view & thisParam)691     void RemoveThisParam(const std::string_view &thisParam)
692     {
693         params_.erase(params_.begin());
694         bindings_.erase(thisParam);
695     }
696 
697     const util::StringView &GetFullScopeName() override;
698     uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override;
699 
700     friend class FunctionScope;
701     template <typename E, typename T>
702     friend class ScopeWithParamScope;
703 
704 private:
705     FunctionScope *functionScope_ {};
706     LocalVariable *nameVar_ {};
707 };
708 
709 template <typename E, typename T>
710 class ScopeWithParamScope : public E {
711 public:
ScopeWithParamScope(ArenaAllocator * allocator,Scope * parent)712     explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent) {}
713 
BindParamScope(T * paramScope)714     void BindParamScope(T *paramScope)
715     {
716         CHECK_NOT_NULL(paramScope);
717         AssignParamScope(paramScope);
718         this->bindings_ = paramScope->Bindings();
719     }
720 
AssignParamScope(T * paramScope)721     void AssignParamScope(T *paramScope)
722     {
723         ASSERT(this->parent_ == paramScope);
724         ASSERT(this->bindings_.empty());
725 
726         paramScope_ = paramScope;
727     }
728 
ParamScope()729     T *ParamScope()
730     {
731         return paramScope_;
732     }
733 
ParamScope()734     const T *ParamScope() const
735     {
736         return paramScope_;
737     }
738 
AddBindsFromParam()739     void AddBindsFromParam()
740     {
741         ASSERT(paramScope_);
742         this->bindings_.insert(paramScope_->Bindings().begin(), paramScope_->Bindings().end());
743     }
744 
HasParamScope()745     bool HasParamScope() override
746     {
747         return true;
748     }
749 
750 protected:
751     T *paramScope_ {nullptr};
752 };
753 
754 class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> {
755 public:
FunctionScope(ArenaAllocator * allocator,Scope * parent)756     explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
757 
Type()758     ScopeType Type() const override
759     {
760         return ScopeType::FUNCTION;
761     }
762 
763     virtual void BindNameWithScopeInfo(util::StringView name, util::StringView recordName);
764 
BindName(util::StringView name,util::StringView internalName)765     void BindName(util::StringView name, util::StringView internalName)
766     {
767         name_ = name;
768         internalName_ = internalName;
769     }
770 
Name()771     const util::StringView &Name() const
772     {
773         return name_;
774     }
775 
InternalName()776     const util::StringView &InternalName() const
777     {
778         return internalName_;
779     }
780 
InFunctionScopes()781     bool InFunctionScopes() const
782     {
783         return inFunctionScopes_;
784     }
785 
SetInFunctionScopes()786     void SetInFunctionScopes()
787     {
788         inFunctionScopes_ = true;
789     }
790 
791     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
792                     [[maybe_unused]] ScriptExtension extension) override;
793 
794     void SetSelfScopeName(const util::StringView &ident) override;
795 
GetFullScopeName()796     const util::StringView &GetFullScopeName() override
797     {
798         SetFullScopeNames();
799         return fullScopeName_;
800     }
801 
GetDuplicateScopeIndex(const util::StringView & childScopeName)802     uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override
803     {
804         auto it = scopesIndex_.find(childScopeName);
805         if (it == scopesIndex_.end()) {
806             scopesIndex_.insert({childScopeName, 0});
807             return 0;
808         } else {
809             return ++it->second;
810         }
811     }
812 
813 protected:
814     util::StringView GetSelfScopeName() override;
815 
GetParentWithScopeName()816     Scope *GetParentWithScopeName() override
817     {
818         Scope *parentScope = parent_;
819         // FunctionParamScope has the same scope name with functionScope
820         // But functionParamScope is the parent of functionScope, it should be skipped here.
821         if ((parentScope != nullptr) && (parentScope->IsFunctionParamScope())) {
822             parentScope = parentScope->Parent();
823         }
824 
825         return parentScope;
826     }
827 
828     util::StringView name_ {};
829     util::StringView internalName_ {};
830 
831 private:
832     util::StringView GetScopeTag() override;
833 
834     bool inFunctionScopes_ {false};
835 };
836 
837 class LocalScope : public Scope {
838 public:
LocalScope(ArenaAllocator * allocator,Scope * parent)839     explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
840 
Type()841     ScopeType Type() const override
842     {
843         return ScopeType::LOCAL;
844     }
845 
846     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
847                     [[maybe_unused]] ScriptExtension extension) override;
848 };
849 
850 class ClassScope : public VariableScope {
851 public:
ClassScope(ArenaAllocator * allocator,Scope * parent)852     explicit ClassScope(ArenaAllocator *allocator, Scope *parent)
853         : VariableScope(allocator, parent),
854           computedNames_(allocator->Adapter()),
855           privateNames_(allocator->Adapter()),
856           privateGetters_(allocator->Adapter()),
857           privateSetters_(allocator->Adapter())
858     {
859     }
860 
861     ~ClassScope() override = default;
862 
863     bool IsVariableScope() const override;
864 
Type()865     ScopeType Type() const override
866     {
867         return ScopeType::CLASS;
868     }
869 
AddClassVariable(const ir::Expression * key)870     void AddClassVariable(const ir::Expression *key)
871     {
872         computedNames_.insert({key, slotIndex_++});
873     }
874 
GetSlot(const ir::Expression * key)875     uint32_t GetSlot(const ir::Expression *key) const
876     {
877         ASSERT(computedNames_.find(key) != computedNames_.end());
878         return computedNames_.find(key)->second;
879     }
880 
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)881     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
882                     [[maybe_unused]] ScriptExtension extension) override
883     {
884         return AddLocal(allocator, currentVariable, newDecl, extension);
885     }
886 
HasPrivateName(const util::StringView & name)887     bool HasPrivateName(const util::StringView &name) const
888     {
889         return (privateNames_.count(name) + privateGetters_.count(name) + privateSetters_.count(name) != 0);
890     }
891 
GetFullScopeName()892     const util::StringView &GetFullScopeName() override
893     {
894         SetFullScopeNames();
895         return fullScopeName_;
896     }
897 
GetDuplicateScopeIndex(const util::StringView & childScopeName)898     uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override
899     {
900         auto it = scopesIndex_.find(childScopeName);
901         if (it == scopesIndex_.end()) {
902             scopesIndex_.insert({childScopeName, 0});
903             return 0;
904         } else {
905             return ++it->second;
906         }
907     }
908 
909     Result GetPrivateProperty(const util::StringView &name, bool isSetter) const;
910     void AddPrivateName(std::vector<const ir::Statement *> privateProperties, uint32_t privateFieldCnt,
911                         uint32_t instancePrivateMethodCnt, uint32_t staticPrivateMethodCnt);
912     friend class ir::ClassDefinition;
913 
914 protected:
915     util::StringView GetSelfScopeName() override;
916 
917 private:
918     util::StringView GetScopeTag() override;
919 
IsMethod(uint32_t slot)920     bool IsMethod(uint32_t slot) const
921     {
922         return slot >= instancePrivateMethodStartSlot_ && slot < privateMethodEndSlot_;
923     }
924 
IsStaticMethod(uint32_t slot)925     bool IsStaticMethod(uint32_t slot) const
926     {
927         return slot >= staticPrivateMethodStartSlot_;
928     }
929 
930     ArenaUnorderedMap<const ir::Expression *, uint32_t> computedNames_;
931     ArenaUnorderedMap<util::StringView, uint32_t> privateNames_;
932     ArenaUnorderedMap<util::StringView, uint32_t> privateGetters_;
933     ArenaUnorderedMap<util::StringView, uint32_t> privateSetters_;
934     uint32_t privateFieldCnt_ {0};
935     uint32_t instancePrivateMethodStartSlot_ {0};
936     uint32_t staticPrivateMethodStartSlot_ {0};
937     uint32_t privateMethodEndSlot_ {0};
938     uint32_t instanceMethodValidation_ {0};
939     uint32_t staticMethodValidation_ {0};
940 };
941 
942 class CatchParamScope : public ParamScope {
943 public:
CatchParamScope(ArenaAllocator * allocator,Scope * parent)944     explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
945 
Type()946     ScopeType Type() const override
947     {
948         return ScopeType::CATCH_PARAM;
949     }
950 
951     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
952                     [[maybe_unused]] ScriptExtension extension) override;
953 
954     friend class CatchScope;
955 };
956 
957 class CatchScope : public ScopeWithParamScope<LocalScope, CatchParamScope> {
958 public:
CatchScope(ArenaAllocator * allocator,Scope * parent)959     explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
960 
Type()961     ScopeType Type() const override
962     {
963         return ScopeType::CATCH;
964     }
965 
966     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
967                     [[maybe_unused]] ScriptExtension extension) override;
968 };
969 
970 class LoopScope : public VariableScope {
971 public:
LoopScope(ArenaAllocator * allocator,Scope * parent)972     explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
973 
Type()974     ScopeType Type() const override
975     {
976         return loopType_;
977     }
978 
979     void InitVariable();
980 
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)981     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
982                     [[maybe_unused]] ScriptExtension extension) override
983     {
984         return AddLocal(allocator, currentVariable, newDecl, extension);
985     }
986 
987 protected:
988     ScopeType loopType_ {ScopeType::LOOP};
989 };
990 
991 class StaticBlockScope : public VariableScope {
992 public:
StaticBlockScope(ArenaAllocator * allocator,Scope * parent)993     explicit StaticBlockScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
994 
Type()995     ScopeType Type() const override
996     {
997         return staticBlockType_;
998     }
999 
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)1000     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
1001                     [[maybe_unused]] ScriptExtension extension) override
1002     {
1003         return AddLocal(allocator, currentVariable, newDecl, extension);
1004     }
1005 
1006 protected:
1007     ScopeType staticBlockType_ {ScopeType::STATIC_BLOCK};
1008 };
1009 
1010 class GlobalScope : public FunctionScope {
1011 public:
GlobalScope(ArenaAllocator * allocator)1012     explicit GlobalScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
1013     {
1014         paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
1015     }
1016 
Type()1017     ScopeType Type() const override
1018     {
1019         return ScopeType::GLOBAL;
1020     }
1021 
1022     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
1023                     [[maybe_unused]] ScriptExtension extension) override;
1024 
1025     void SetSelfScopeName([[maybe_unused]] const util::StringView &ident) override;
1026 
BindNameWithScopeInfo(util::StringView name,util::StringView recordName)1027     void BindNameWithScopeInfo(util::StringView name, util::StringView recordName) override
1028     {
1029         // only func_main_0 will call BindNameWithScopeInfo() of GlobalScope
1030         name_ = name;
1031         std::stringstream internalName;
1032         internalName << recordName << name;
1033         internalName_ = util::UString(internalName.str(), allocator_).View();
1034     }
1035 
GetFullScopeName()1036     const util::StringView &GetFullScopeName() override
1037     {
1038         return fullScopeName_;
1039     }
1040 };
1041 
1042 class ModuleScope : public FunctionScope {
1043 public:
ModuleScope(ArenaAllocator * allocator,parser::Program * program)1044     explicit ModuleScope(ArenaAllocator *allocator, parser::Program *program) : FunctionScope(allocator, nullptr)
1045     {
1046         paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
1047         program_ = program;
1048     }
1049 
Type()1050     ScopeType Type() const override
1051     {
1052         return ScopeType::MODULE;
1053     }
1054 
Program()1055     const parser::Program *Program() const
1056     {
1057         return program_;
1058     }
1059 
1060     void AssignIndexToModuleVariable(util::StringView name, uint32_t index);
1061 
1062     void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName);
1063 
1064     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
1065                     [[maybe_unused]] ScriptExtension extension) override;
1066 
1067     void SetSelfScopeName([[maybe_unused]] const util::StringView &ident) override;
1068 
BindNameWithScopeInfo(util::StringView name,util::StringView recordName)1069     void BindNameWithScopeInfo(util::StringView name, util::StringView recordName) override
1070     {
1071         // only func_main_0 will call BindNameWithScopeInfo() of ModuleScope
1072         name_ = name;
1073         std::stringstream internalName;
1074         internalName << recordName << name;
1075         internalName_ = util::UString(internalName.str(), allocator_).View();
1076     }
1077 
GetFullScopeName()1078     const util::StringView &GetFullScopeName() override
1079     {
1080         return fullScopeName_;
1081     }
1082 
1083 private:
1084     parser::Program *program_ {nullptr};
1085 };
1086 
1087 class TSModuleScope : public FunctionScope {
1088 public:
TSModuleScope(ArenaAllocator * allocator,Scope * parent,ExportBindings * exportBindings)1089     explicit TSModuleScope(ArenaAllocator *allocator, Scope *parent, ExportBindings *exportBindings)
1090         : FunctionScope(allocator, nullptr), exportBindings_(exportBindings), variableNames_(allocator->Adapter())
1091     {
1092         paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
1093         CHECK_NOT_NULL(paramScope_);
1094         paramScope_->BindFunctionScope(this);
1095         SetParent(paramScope_);
1096     }
1097 
Type()1098     ScopeType Type() const override
1099     {
1100         return ScopeType::TSMODULE;
1101     }
1102 
1103     template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)1104     Variable *FindExportTSVariable(const util::StringView &name) const
1105     {
1106         return exportBindings_->FindExportTSVariable<type>(name);
1107     }
1108 
1109     template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)1110     bool AddExportTSVariable(const util::StringView &name, Variable *var)
1111     {
1112         return exportBindings_->AddExportTSVariable<type>(name, var);
1113     }
1114 
FindExportVariable(const util::StringView & name)1115     Variable *FindExportVariable(const util::StringView &name) const
1116     {
1117         return exportBindings_->FindExportVariable(name);
1118     }
1119 
AddExportVariable(const util::StringView & name,Variable * var)1120     bool AddExportVariable(const util::StringView &name, Variable *var)
1121     {
1122         return exportBindings_->AddExportVariable(name, var);
1123     }
1124 
AddExportVariable(const util::StringView & name)1125     bool AddExportVariable(const util::StringView &name)
1126     {
1127         return exportBindings_->AddExportVariable(name, FindLocal(name));
1128     }
1129 
InExportBindings(const util::StringView & name)1130     bool InExportBindings(const util::StringView &name) const
1131     {
1132         return exportBindings_->InExportBindings(name);
1133     }
1134 
AddDeclarationName(const util::StringView & name)1135     void AddDeclarationName(const util::StringView &name)
1136     {
1137         variableNames_.insert(name);
1138     }
1139 
HasVariableName(const util::StringView & name)1140     bool HasVariableName(const util::StringView &name) const
1141     {
1142         return variableNames_.find(name) != variableNames_.end();
1143     }
1144 
1145 protected:
1146     util::StringView GetSelfScopeName() override;
1147 
1148 private:
1149     util::StringView GetScopeTag() override;
1150 
1151     ExportBindings *exportBindings_;
1152     ArenaSet<util::StringView> variableNames_;
1153 };
1154 
1155 class TSEnumScope : public FunctionScope {
1156 public:
TSEnumScope(ArenaAllocator * allocator,Scope * parent,VariableMap * enumMemberBindings)1157     explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope(
1158         allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter())
1159     {
1160         paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
1161         CHECK_NOT_NULL(paramScope_);
1162         paramScope_->BindFunctionScope(this);
1163         SetParent(paramScope_);
1164         scopeDuplicateIndex_ = parent->GetDuplicateScopeIndex(GetScopeTag());
1165     }
1166 
Type()1167     ScopeType Type() const override
1168     {
1169         return ScopeType::TSENUM;
1170     }
1171 
FindEnumMemberVariable(const util::StringView & name)1172     Variable *FindEnumMemberVariable(const util::StringView &name) const
1173     {
1174         auto res = enumMemberBindings_->find(name);
1175         if (res == enumMemberBindings_->end()) {
1176             return nullptr;
1177         }
1178         return res->second;
1179     }
1180 
AddDeclarationName(const util::StringView & name)1181     void AddDeclarationName(const util::StringView &name)
1182     {
1183         variableNames_.insert(name);
1184     }
1185 
HasDeclarationName(const util::StringView & name)1186     bool HasDeclarationName(const util::StringView &name) const
1187     {
1188         return variableNames_.find(name) != variableNames_.end();
1189     }
1190 
1191     bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
1192                     [[maybe_unused]] ScriptExtension extension) override;
1193 
1194     void SetSelfScopeName(const util::StringView &ident) override;
1195 
1196 protected:
1197     util::StringView GetSelfScopeName() override;
1198 
1199 private:
1200     util::StringView GetScopeTag() override;
1201 
1202     VariableMap *enumMemberBindings_;
1203     ArenaSet<util::StringView> variableNames_;
1204 };
1205 
DeclFlagToVariableFlag(DeclarationFlags declFlag)1206 inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag)
1207 {
1208     VariableFlags varFlag = VariableFlags::NONE;
1209     if (declFlag & DeclarationFlags::EXPORT) {
1210         varFlag = VariableFlags::LOCAL_EXPORT;
1211     } else if (declFlag & DeclarationFlags::IMPORT) {
1212         varFlag = VariableFlags::IMPORT;
1213     }
1214     return varFlag;
1215 }
1216 
1217 template <typename T>
AddVar(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)1218 bool VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
1219 {
1220     VariableFlags flags = VariableFlags::HOIST_VAR;
1221     flags |= DeclFlagToVariableFlag(newDecl->Flags());
1222 
1223     if (!currentVariable) {
1224         bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
1225         return true;
1226     }
1227 
1228     switch (currentVariable->Declaration()->Type()) {
1229         case DeclType::VAR: {
1230             currentVariable->Reset(newDecl, flags);
1231             break;
1232         }
1233         case DeclType::PARAM:
1234         case DeclType::FUNC: {
1235             break;
1236         }
1237         default: {
1238             return false;
1239         }
1240     }
1241 
1242     return true;
1243 }
1244 
1245 template <typename T>
AddFunction(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)1246 bool VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
1247                                 [[maybe_unused]] ScriptExtension extension)
1248 {
1249     VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST;
1250     flags |= DeclFlagToVariableFlag(newDecl->Flags());
1251 
1252     if (!currentVariable) {
1253         bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
1254         return true;
1255     }
1256 
1257     auto decl = currentVariable->Declaration();
1258     if (decl->IsClassDecl() && decl->AsClassDecl()->IsDeclare()) {
1259         newDecl->AsFunctionDecl()->SetDeclClass(decl->AsClassDecl());
1260         bindings_[newDecl->Name()] = allocator->New<T>(newDecl, flags);
1261         return true;
1262     }
1263 
1264     if (extension != ScriptExtension::JS) {
1265         return false;
1266     }
1267 
1268     switch (currentVariable->Declaration()->Type()) {
1269         case DeclType::VAR:
1270         case DeclType::FUNC: {
1271             currentVariable->Reset(newDecl, flags);
1272             break;
1273         }
1274         default: {
1275             return false;
1276         }
1277     }
1278 
1279     return true;
1280 }
1281 
1282 template <typename T>
AddClass(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)1283 bool VariableScope::AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
1284 {
1285     ASSERT(newDecl->IsClassDecl());
1286 
1287     VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
1288 
1289     if (!currentVariable) {
1290         bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
1291         return true;
1292     }
1293 
1294     auto decl = currentVariable->Declaration();
1295     if (newDecl->AsClassDecl()->IsDeclare() && decl->IsFunctionDecl()) {
1296         decl->AsFunctionDecl()->SetDeclClass(newDecl->AsClassDecl());
1297         return true;
1298     }
1299 
1300     return false;
1301 }
1302 
1303 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,VariableFlags flags)1304 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, Decl *newDecl,
1305                                  VariableFlags flags)
1306 {
1307     ASSERT(!currentVariable);
1308     // TODO(xucheng): move the ts variables to tsBindings_
1309     bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
1310     return true;
1311 }
1312 
1313 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Decl * newDecl,VariableFlags flags)1314 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags)
1315 {
1316     switch (flags) {
1317         case VariableFlags::NAMESPACE: {
1318             return tsBindings_.AddTSVariable<TSBindingType::NAMESPACE>(
1319                 newDecl->Name(), allocator->New<T>(newDecl, flags));
1320         }
1321         case VariableFlags::ENUM_LITERAL: {
1322             return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>(
1323                 newDecl->Name(), allocator->New<T>(newDecl, flags));
1324         }
1325         case VariableFlags::INTERFACE: {
1326             return tsBindings_.AddTSVariable<TSBindingType::INTERFACE>(
1327                 newDecl->Name(), allocator->New<T>(newDecl, flags));
1328         }
1329         case VariableFlags::IMPORT_EQUALS: {
1330             return tsBindings_.AddTSVariable<TSBindingType::IMPORT_EQUALS>(
1331                 newDecl->Name(), allocator->New<T>(newDecl, flags));
1332         }
1333         default: {
1334             break;
1335         }
1336     }
1337     return false;
1338 }
1339 
1340 template <typename T>
AddLexical(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)1341 bool VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
1342 {
1343     VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
1344 
1345     if (currentVariable) {
1346         return false;
1347     }
1348 
1349     bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
1350     return true;
1351 }
1352 
1353 template <typename T, typename... Args>
NewDecl(ArenaAllocator * allocator,Args &&...args)1354 T *Scope::NewDecl(ArenaAllocator *allocator, Args &&... args)
1355 {
1356     T *decl = allocator->New<T>(std::forward<Args>(args)...);
1357     decls_.push_back(decl);
1358 
1359     return decl;
1360 }
1361 
1362 template <typename DeclType, typename VariableType>
AddDecl(ArenaAllocator * allocator,util::StringView name,VariableFlags flags)1363 VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags)
1364 {
1365     if (FindLocal(name)) {
1366         return nullptr;
1367     }
1368 
1369     auto *decl = allocator->New<DeclType>(name);
1370     auto *variable = allocator->New<VariableType>(decl, flags);
1371     CHECK_NOT_NULL(decl);
1372     CHECK_NOT_NULL(variable);
1373 
1374     decls_.push_back(decl);
1375     bindings_.insert({decl->Name(), variable});
1376 
1377     return variable;
1378 }
1379 
1380 template <typename DeclType, typename VariableType>
CreateVar(ArenaAllocator * allocator,util::StringView name,VariableFlags flags,const ir::AstNode * node)1381 VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
1382                                const ir::AstNode *node)
1383 {
1384     auto *decl = allocator->New<DeclType>(name);
1385     CHECK_NOT_NULL(decl);
1386     auto *variable = allocator->New<VariableType>(decl, flags);
1387     CHECK_NOT_NULL(variable);
1388     decl->BindNode(node);
1389     return variable;
1390 }
1391 
1392 template <typename T, typename... Args>
PropagateBinding(ArenaAllocator * allocator,util::StringView name,Args &&...args)1393 void Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args)
1394 {
1395     auto res = bindings_.find(name);
1396     if (res == bindings_.end()) {
1397         bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)});
1398         return;
1399     }
1400 
1401     if (!res->second->Declaration()->IsParameterDecl()) {
1402         res->second->Reset(std::forward<Args>(args)...);
1403     }
1404 }
1405 
1406 }  // namespace panda::es2panda::binder
1407 
1408 #endif
1409