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