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::binder {
34
35 #define DECLARE_CLASSES(type, className) class className;
36 SCOPE_TYPES(DECLARE_CLASSES)
37 #undef DECLARE_CLASSES
38
39 class Scope;
40 class VariableScope;
41 class Variable;
42
43 using VariableMap = ArenaUnorderedMap<util::StringView, Variable *>;
44
45 class TSBindings {
46 public:
TSBindings(ArenaAllocator * allocator)47 explicit TSBindings(ArenaAllocator *allocator) : allocator_(allocator) {}
48
49 template <TSBindingType type>
AddTSVariable(const util::StringView & name,Variable * variable)50 bool AddTSVariable(const util::StringView &name, Variable *variable)
51 {
52 static_assert(type < TSBindingType::COUNT);
53 size_t index = GetIndex(type);
54 if (tsBindings_[index] == nullptr) {
55 tsBindings_[index] = allocator_->New<VariableMap>(allocator_->Adapter());
56 }
57 return tsBindings_[index]->insert({name, variable}).second;
58 }
59
60 template <TSBindingType type>
FindTSVariable(const util::StringView & name)61 Variable *FindTSVariable(const util::StringView &name) const
62 {
63 static_assert(type < TSBindingType::COUNT);
64 size_t index = GetIndex(type);
65 if (tsBindings_[index] == nullptr) {
66 return nullptr;
67 }
68 auto res = tsBindings_[index]->find(name);
69 if (res == tsBindings_[index]->end()) {
70 return nullptr;
71 }
72 return res->second;
73 }
74
InTSBindings(const util::StringView & name)75 bool InTSBindings(const util::StringView &name) const
76 {
77 for (size_t i = 0; i < GetIndex(TSBindingType::COUNT); i++) {
78 if (tsBindings_[i] && tsBindings_[i]->find(name) != tsBindings_[i]->end()) {
79 return true;
80 }
81 }
82 return false;
83 }
84
85 private:
GetIndex(TSBindingType type)86 size_t GetIndex(TSBindingType type) const
87 {
88 return static_cast<size_t>(type);
89 }
90
91 ArenaAllocator *allocator_;
92 std::array<VariableMap *, static_cast<size_t>(TSBindingType::COUNT)> tsBindings_ {};
93 };
94
95 class ExportBindings {
96 public:
ExportBindings(ArenaAllocator * allocator)97 explicit ExportBindings(ArenaAllocator *allocator)
98 : exportBindings_(allocator->Adapter()),
99 exportTSBindings_(allocator)
100 {
101 }
102
FindExportVariable(const util::StringView & name)103 Variable *FindExportVariable(const util::StringView &name) const
104 {
105 auto res = exportBindings_.find(name);
106 if (res == exportBindings_.end()) {
107 return nullptr;
108 }
109 return res->second;
110 }
111
AddExportVariable(const util::StringView & name,Variable * var)112 bool AddExportVariable(const util::StringView &name, Variable *var)
113 {
114 return exportBindings_.insert({name, var}).second;
115 }
116
InExportBindings(const util::StringView & name)117 bool InExportBindings(const util::StringView &name) const
118 {
119 auto res = FindExportVariable(name);
120 return res != nullptr || exportTSBindings_.InTSBindings(name);
121 }
122
123 template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)124 Variable *FindExportTSVariable(const util::StringView &name) const
125 {
126 return exportTSBindings_.FindTSVariable<type>(name);
127 }
128
129 template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)130 bool AddExportTSVariable(const util::StringView &name, Variable *var)
131 {
132 return exportTSBindings_.AddTSVariable<type>(name, var);
133 }
134
135 private:
136 VariableMap exportBindings_;
137 TSBindings exportTSBindings_;
138 };
139
140 class ScopeFindResult {
141 public:
142 ScopeFindResult() = default;
ScopeFindResult(util::StringView n,Scope * s,uint32_t l,Variable * v)143 ScopeFindResult(util::StringView n, Scope *s, uint32_t l, Variable *v) : ScopeFindResult(n, s, l, l, v, false) {}
ScopeFindResult(Scope * s,uint32_t l,uint32_t ll,Variable * v)144 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,Variable * v,bool c)145 ScopeFindResult(util::StringView n, Scope *s, uint32_t l, uint32_t ll, Variable *v, bool c)
146 : name(n), scope(s), level(l), lexLevel(ll), variable(v), crossConcurrent(c)
147 {
148 }
149
150 util::StringView name {};
151 Scope *scope {};
152 uint32_t level {};
153 uint32_t lexLevel {};
154 Variable *variable {};
155 bool crossConcurrent {false};
156 };
157
158 class Scope {
159 public:
160 virtual ~Scope() = default;
161 NO_COPY_SEMANTIC(Scope);
162 NO_MOVE_SEMANTIC(Scope);
163
164 virtual ScopeType Type() const = 0;
165
166 #define DECLARE_CHECKS_CASTS(scopeType, className) \
167 bool Is##className() const \
168 { \
169 return Type() == ScopeType::scopeType; \
170 } \
171 className *As##className() \
172 { \
173 ASSERT(Is##className()); \
174 return reinterpret_cast<className *>(this); \
175 } \
176 const className *As##className() const \
177 { \
178 ASSERT(Is##className()); \
179 return reinterpret_cast<const className *>(this); \
180 }
SCOPE_TYPES(DECLARE_CHECKS_CASTS)181 SCOPE_TYPES(DECLARE_CHECKS_CASTS)
182 #undef DECLARE_CHECKS_CASTS
183
184 bool IsVariableScope() const
185 {
186 return Type() > ScopeType::LOCAL;
187 }
188
IsFunctionVariableScope()189 bool IsFunctionVariableScope() const
190 {
191 return Type() >= ScopeType::FUNCTION;
192 }
193
AsFunctionVariableScope()194 FunctionScope *AsFunctionVariableScope()
195 {
196 ASSERT(IsFunctionVariableScope());
197 return reinterpret_cast<FunctionScope *>(this);
198 }
199
AsFunctionVariableScope()200 const FunctionScope *AsFunctionVariableScope() const
201 {
202 ASSERT(IsFunctionVariableScope());
203 return reinterpret_cast<const FunctionScope *>(this);
204 }
205
AsVariableScope()206 VariableScope *AsVariableScope()
207 {
208 ASSERT(IsVariableScope());
209 return reinterpret_cast<VariableScope *>(this);
210 }
211
AsVariableScope()212 const VariableScope *AsVariableScope() const
213 {
214 ASSERT(IsVariableScope());
215 return reinterpret_cast<const VariableScope *>(this);
216 }
217
218 VariableScope *EnclosingVariableScope();
219
220 FunctionScope *EnclosingFunctionVariableScope();
221
Decls()222 const ArenaVector<Decl *> &Decls() const
223 {
224 return decls_;
225 }
226
Parent()227 Scope *Parent()
228 {
229 return parent_;
230 }
231
Parent()232 const Scope *Parent() const
233 {
234 return parent_;
235 }
236
SetParent(Scope * parent)237 void SetParent(Scope *parent)
238 {
239 parent_ = parent;
240 }
241
ScopeStart()242 const compiler::IRNode *ScopeStart() const
243 {
244 return startIns_;
245 }
246
ScopeEnd()247 const compiler::IRNode *ScopeEnd() const
248 {
249 return endIns_;
250 }
251
SetScopeStart(const compiler::IRNode * ins)252 void SetScopeStart(const compiler::IRNode *ins)
253 {
254 startIns_ = ins;
255 }
256
SetScopeEnd(const compiler::IRNode * ins)257 void SetScopeEnd(const compiler::IRNode *ins)
258 {
259 endIns_ = ins;
260 }
261
Node()262 const ir::AstNode *Node() const
263 {
264 return node_;
265 }
266
Node()267 ir::AstNode *Node()
268 {
269 return node_;
270 }
271
BindNode(ir::AstNode * node)272 void BindNode(ir::AstNode *node)
273 {
274 node_ = node;
275 }
276
AddDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)277 bool AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
278 {
279 decls_.push_back(decl);
280 return AddBinding(allocator, FindLocal(decl->Name()), decl, extension);
281 }
282
AddTsDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)283 bool AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
284 {
285 decls_.push_back(decl);
286 return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension);
287 }
288
289 template <typename T, typename... Args>
290 T *NewDecl(ArenaAllocator *allocator, Args &&... args);
291
292 template <typename DeclType, typename VariableType>
293 VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags);
294
295 template <typename DeclType = binder::LetDecl, typename VariableType = binder::LocalVariable>
296 static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
297 const ir::AstNode *node);
298
299 template <typename T, typename... Args>
300 void PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args);
301
Bindings()302 VariableMap &Bindings()
303 {
304 return bindings_;
305 }
306
Bindings()307 const VariableMap &Bindings() const
308 {
309 return bindings_;
310 }
311
312 virtual bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
313 [[maybe_unused]] ScriptExtension extension) = 0;
314
315 Variable *FindLocal(const util::StringView &name,
316 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
317
318 ScopeFindResult Find(const util::StringView &name,
319 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
320
321 Decl *FindDecl(const util::StringView &name) const;
322
323 bool HasVarDecl(const util::StringView &name) const;
324
325 bool HasLexEnvInCorrespondingFunctionScope(const FunctionParamScope *scope) const;
326
327 template <TSBindingType type>
FindLocalTSVariable(const util::StringView & name)328 Variable *FindLocalTSVariable(const util::StringView &name) const
329 {
330 return tsBindings_.FindTSVariable<type>(name);
331 }
332
333 template <TSBindingType type>
AddLocalTSVariable(const util::StringView & name,Variable * var)334 void AddLocalTSVariable(const util::StringView &name, Variable *var)
335 {
336 tsBindings_.AddTSVariable<type>(name, var);
337 }
338
InLocalTSBindings(const util::StringView & name)339 bool InLocalTSBindings(const util::StringView &name) const
340 {
341 return tsBindings_.InTSBindings(name);
342 }
343
344 protected:
Scope(ArenaAllocator * allocator,Scope * parent)345 explicit Scope(ArenaAllocator *allocator, Scope *parent)
346 : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()), tsBindings_(allocator)
347 {
348 }
349
350 /**
351 * @return true - if the variable is shadowed
352 * false - otherwise
353 */
354 using VariableVisitior = std::function<bool(const Variable *)>;
355
356 /**
357 * @return true - if the variable is shadowed
358 * false - otherwise
359 */
360 std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor);
361
362 bool AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
363 [[maybe_unused]] ScriptExtension extension);
364
365 Scope *parent_ {};
366 ArenaVector<Decl *> decls_;
367 VariableMap bindings_;
368 TSBindings tsBindings_;
369 ir::AstNode *node_ {};
370 const compiler::IRNode *startIns_ {};
371 const compiler::IRNode *endIns_ {};
372 };
373
374 class VariableScope : public Scope {
375 public:
376 ~VariableScope() override = default;
377 NO_COPY_SEMANTIC(VariableScope);
378 NO_MOVE_SEMANTIC(VariableScope);
379
AddFlag(VariableScopeFlags flag)380 void AddFlag(VariableScopeFlags flag)
381 {
382 flags_ |= flag;
383 }
384
ClearFlag(VariableScopeFlags flag)385 void ClearFlag(VariableScopeFlags flag)
386 {
387 flags_ &= ~flag;
388 }
389
HasFlag(VariableScopeFlags flag)390 bool HasFlag(VariableScopeFlags flag) const
391 {
392 return (flags_ & flag) != 0;
393 }
394
NextSlot()395 uint32_t NextSlot()
396 {
397 return slotIndex_++;
398 }
399
LexicalSlots()400 uint32_t LexicalSlots() const
401 {
402 return slotIndex_;
403 }
404
NeedLexEnv()405 bool NeedLexEnv() const
406 {
407 return slotIndex_ != 0;
408 }
409
AddLexicalVarNameAndType(uint32_t slot,util::StringView name,int type)410 void AddLexicalVarNameAndType(uint32_t slot, util::StringView name, int type)
411 {
412 lexicalVarNameAndTypes_.emplace(slot, std::pair<util::StringView, int>(name, type));
413 }
414
GetLexicalVarNameAndTypes()415 ArenaMap<uint32_t, std::pair<util::StringView, int>> &GetLexicalVarNameAndTypes()
416 {
417 return lexicalVarNameAndTypes_;
418 }
419
420 protected:
VariableScope(ArenaAllocator * allocator,Scope * parent)421 explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent),
422 lexicalVarNameAndTypes_(allocator->Adapter()) {}
423
424 inline VariableFlags DeclFlagToVariableFlag(DeclarationFlags declFlag);
425
426 template <typename T>
427 bool AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
428
429 template <typename T>
430 bool AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
431 [[maybe_unused]] ScriptExtension extension);
432
433 template <typename T>
434 bool AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
435
436 template <typename T>
437 bool AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
438
439 template <typename T>
440 bool AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags);
441
442 template <typename T>
443 bool AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
444
445 VariableScopeFlags flags_ {};
446 uint32_t slotIndex_ {};
447 ArenaMap<uint32_t, std::pair<util::StringView, int>> lexicalVarNameAndTypes_; // for debuginfo and patchFix
448 };
449
450 class ParamScope : public Scope {
451 public:
Type()452 ScopeType Type() const override
453 {
454 return ScopeType::PARAM;
455 }
456
Params()457 ArenaVector<LocalVariable *> &Params()
458 {
459 return params_;
460 }
461
Params()462 const ArenaVector<LocalVariable *> &Params() const
463 {
464 return params_;
465 }
466
HasParam(util::StringView name)467 bool HasParam(util::StringView name) const
468 {
469 for (auto *param : params_) {
470 if (param->Name() == name) {
471 return true;
472 }
473 }
474
475 return false;
476 }
477
478 std::tuple<ParameterDecl *, const ir::AstNode *> AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param);
479
480 protected:
ParamScope(ArenaAllocator * allocator,Scope * parent)481 explicit ParamScope(ArenaAllocator *allocator, Scope *parent)
482 : Scope(allocator, parent), params_(allocator->Adapter())
483 {
484 }
485
486 bool AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
487
488 ArenaVector<LocalVariable *> params_;
489 };
490
491 class FunctionScope;
492
493 class FunctionParamScope : public ParamScope {
494 public:
FunctionParamScope(ArenaAllocator * allocator,Scope * parent)495 explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
496
GetFunctionScope()497 FunctionScope *GetFunctionScope() const
498 {
499 return functionScope_;
500 }
501
BindFunctionScope(FunctionScope * funcScope)502 void BindFunctionScope(FunctionScope *funcScope)
503 {
504 functionScope_ = funcScope;
505 }
506
NameVar()507 LocalVariable *NameVar() const
508 {
509 return nameVar_;
510 }
511
512 void BindName(ArenaAllocator *allocator, util::StringView name);
513
Type()514 ScopeType Type() const override
515 {
516 return ScopeType::FUNCTION_PARAM;
517 }
518
519 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
520 [[maybe_unused]] ScriptExtension extension) override;
521
RemoveThisParam(const std::string_view & thisParam)522 void RemoveThisParam(const std::string_view &thisParam)
523 {
524 params_.erase(params_.begin());
525 bindings_.erase(thisParam);
526 }
527
528 friend class FunctionScope;
529 template <typename E, typename T>
530 friend class ScopeWithParamScope;
531
532 private:
533 FunctionScope *functionScope_ {};
534 LocalVariable *nameVar_ {};
535 };
536
537 template <typename E, typename T>
538 class ScopeWithParamScope : public E {
539 public:
ScopeWithParamScope(ArenaAllocator * allocator,Scope * parent)540 explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent) {}
541
BindParamScope(T * paramScope)542 void BindParamScope(T *paramScope)
543 {
544 AssignParamScope(paramScope);
545 this->bindings_ = paramScope->Bindings();
546 }
547
AssignParamScope(T * paramScope)548 void AssignParamScope(T *paramScope)
549 {
550 ASSERT(this->parent_ == paramScope);
551 ASSERT(this->bindings_.empty());
552
553 paramScope_ = paramScope;
554 }
555
ParamScope()556 T *ParamScope()
557 {
558 return paramScope_;
559 }
560
ParamScope()561 const T *ParamScope() const
562 {
563 return paramScope_;
564 }
565
AddBindsFromParam()566 void AddBindsFromParam()
567 {
568 ASSERT(paramScope_);
569 this->bindings_.insert(paramScope_->Bindings().begin(), paramScope_->Bindings().end());
570 }
571
572 protected:
573 T *paramScope_;
574 };
575
576 class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> {
577 public:
FunctionScope(ArenaAllocator * allocator,Scope * parent)578 explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
579
Type()580 ScopeType Type() const override
581 {
582 return ScopeType::FUNCTION;
583 }
584
BindName(util::StringView name,util::StringView internalName)585 void BindName(util::StringView name, util::StringView internalName)
586 {
587 name_ = name;
588 internalName_ = internalName;
589 }
590
Name()591 const util::StringView &Name() const
592 {
593 return name_;
594 }
595
InternalName()596 const util::StringView &InternalName() const
597 {
598 return internalName_;
599 }
600
InFunctionScopes()601 bool InFunctionScopes() const
602 {
603 return inFunctionScopes_;
604 }
605
SetInFunctionScopes()606 void SetInFunctionScopes()
607 {
608 inFunctionScopes_ = true;
609 }
610
611 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
612 [[maybe_unused]] ScriptExtension extension) override;
613
614 private:
615 util::StringView name_ {};
616 util::StringView internalName_ {};
617 bool inFunctionScopes_ {false};
618 };
619
620 class LocalScope : public Scope {
621 public:
LocalScope(ArenaAllocator * allocator,Scope * parent)622 explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
623
Type()624 ScopeType Type() const override
625 {
626 return ScopeType::LOCAL;
627 }
628
629 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
630 [[maybe_unused]] ScriptExtension extension) override;
631 };
632
633 class CatchParamScope : public ParamScope {
634 public:
CatchParamScope(ArenaAllocator * allocator,Scope * parent)635 explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
636
Type()637 ScopeType Type() const override
638 {
639 return ScopeType::CATCH_PARAM;
640 }
641
642 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
643 [[maybe_unused]] ScriptExtension extension) override;
644
645 friend class CatchScope;
646 };
647
648 class CatchScope : public ScopeWithParamScope<LocalScope, CatchParamScope> {
649 public:
CatchScope(ArenaAllocator * allocator,Scope * parent)650 explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
651
Type()652 ScopeType Type() const override
653 {
654 return ScopeType::CATCH;
655 }
656
657 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
658 [[maybe_unused]] ScriptExtension extension) override;
659 };
660
661 class LoopScope : public VariableScope {
662 public:
LoopScope(ArenaAllocator * allocator,Scope * parent)663 explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
664
Type()665 ScopeType Type() const override
666 {
667 return loopType_;
668 }
669
670 void InitVariable();
671
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)672 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
673 [[maybe_unused]] ScriptExtension extension) override
674 {
675 return AddLocal(allocator, currentVariable, newDecl, extension);
676 }
677
678 protected:
679 ScopeType loopType_ {ScopeType::LOOP};
680 };
681
682 class GlobalScope : public FunctionScope {
683 public:
GlobalScope(ArenaAllocator * allocator)684 explicit GlobalScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
685 {
686 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
687 }
688
Type()689 ScopeType Type() const override
690 {
691 return ScopeType::GLOBAL;
692 }
693
694 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
695 [[maybe_unused]] ScriptExtension extension) override;
696 };
697
698 class ModuleScope : public FunctionScope {
699 public:
ModuleScope(ArenaAllocator * allocator)700 explicit ModuleScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
701 {
702 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
703 }
704
Type()705 ScopeType Type() const override
706 {
707 return ScopeType::MODULE;
708 }
709
710 void AssignIndexToModuleVariable(util::StringView name, uint32_t index);
711
712 void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName);
713
714 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
715 [[maybe_unused]] ScriptExtension extension) override;
716 };
717
718 class TSModuleScope : public FunctionScope {
719 public:
TSModuleScope(ArenaAllocator * allocator,Scope * parent,ExportBindings * exportBindings)720 explicit TSModuleScope(ArenaAllocator *allocator, Scope *parent, ExportBindings *exportBindings)
721 : FunctionScope(allocator, nullptr), exportBindings_(exportBindings), variableNames_(allocator->Adapter())
722 {
723 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
724 paramScope_->BindFunctionScope(this);
725 SetParent(paramScope_);
726 }
727
Type()728 ScopeType Type() const override
729 {
730 return ScopeType::TSMODULE;
731 }
732
733 template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)734 Variable *FindExportTSVariable(const util::StringView &name) const
735 {
736 return exportBindings_->FindExportTSVariable<type>(name);
737 }
738
739 template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)740 bool AddExportTSVariable(const util::StringView &name, Variable *var)
741 {
742 return exportBindings_->AddExportTSVariable<type>(name, var);
743 }
744
FindExportVariable(const util::StringView & name)745 Variable *FindExportVariable(const util::StringView &name) const
746 {
747 return exportBindings_->FindExportVariable(name);
748 }
749
AddExportVariable(const util::StringView & name,Variable * var)750 bool AddExportVariable(const util::StringView &name, Variable *var)
751 {
752 return exportBindings_->AddExportVariable(name, var);
753 }
754
AddExportVariable(const util::StringView & name)755 bool AddExportVariable(const util::StringView &name)
756 {
757 return exportBindings_->AddExportVariable(name, FindLocal(name));
758 }
759
InExportBindings(const util::StringView & name)760 bool InExportBindings(const util::StringView &name) const
761 {
762 return exportBindings_->InExportBindings(name);
763 }
764
AddDeclarationName(const util::StringView & name)765 void AddDeclarationName(const util::StringView &name)
766 {
767 variableNames_.insert(name);
768 }
769
HasVariableName(const util::StringView & name)770 bool HasVariableName(const util::StringView &name) const
771 {
772 return variableNames_.find(name) != variableNames_.end();
773 }
774
775 private:
776 ExportBindings *exportBindings_;
777 ArenaSet<util::StringView> variableNames_;
778 };
779
780 class TSEnumScope : public FunctionScope {
781 public:
TSEnumScope(ArenaAllocator * allocator,Scope * parent,VariableMap * enumMemberBindings)782 explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope(
783 allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter())
784 {
785 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
786 paramScope_->BindFunctionScope(this);
787 SetParent(paramScope_);
788 }
789
Type()790 ScopeType Type() const override
791 {
792 return ScopeType::TSENUM;
793 }
794
FindEnumMemberVariable(const util::StringView & name)795 Variable *FindEnumMemberVariable(const util::StringView &name) const
796 {
797 auto res = enumMemberBindings_->find(name);
798 if (res == enumMemberBindings_->end()) {
799 return nullptr;
800 }
801 return res->second;
802 }
803
AddDeclarationName(const util::StringView & name)804 void AddDeclarationName(const util::StringView &name)
805 {
806 variableNames_.insert(name);
807 }
808
HasDeclarationName(const util::StringView & name)809 bool HasDeclarationName(const util::StringView &name) const
810 {
811 return variableNames_.find(name) != variableNames_.end();
812 }
813
814 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
815 [[maybe_unused]] ScriptExtension extension) override;
816
817 private:
818 VariableMap *enumMemberBindings_;
819 ArenaSet<util::StringView> variableNames_;
820 };
821
DeclFlagToVariableFlag(DeclarationFlags declFlag)822 inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag)
823 {
824 VariableFlags varFlag = VariableFlags::NONE;
825 if (declFlag & DeclarationFlags::EXPORT) {
826 varFlag = VariableFlags::LOCAL_EXPORT;
827 } else if (declFlag & DeclarationFlags::IMPORT) {
828 varFlag = VariableFlags::IMPORT;
829 }
830 return varFlag;
831 }
832
833 template <typename T>
AddVar(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)834 bool VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
835 {
836 VariableFlags flags = VariableFlags::HOIST_VAR;
837 flags |= DeclFlagToVariableFlag(newDecl->Flags());
838
839 if (!currentVariable) {
840 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
841 return true;
842 }
843
844 switch (currentVariable->Declaration()->Type()) {
845 case DeclType::VAR: {
846 currentVariable->Reset(newDecl, flags);
847 break;
848 }
849 case DeclType::PARAM:
850 case DeclType::FUNC: {
851 break;
852 }
853 default: {
854 return false;
855 }
856 }
857
858 return true;
859 }
860
861 template <typename T>
AddFunction(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)862 bool VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
863 [[maybe_unused]] ScriptExtension extension)
864 {
865 VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST;
866 flags |= DeclFlagToVariableFlag(newDecl->Flags());
867
868 if (!currentVariable) {
869 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
870 return true;
871 }
872
873 auto decl = currentVariable->Declaration();
874 if (decl->IsClassDecl() && decl->AsClassDecl()->IsDeclare()) {
875 newDecl->AsFunctionDecl()->SetDeclClass(decl->AsClassDecl());
876 bindings_[newDecl->Name()] = allocator->New<T>(newDecl, flags);
877 return true;
878 }
879
880 if (extension != ScriptExtension::JS) {
881 return false;
882 }
883
884 switch (currentVariable->Declaration()->Type()) {
885 case DeclType::VAR:
886 case DeclType::FUNC: {
887 currentVariable->Reset(newDecl, flags);
888 break;
889 }
890 default: {
891 return false;
892 }
893 }
894
895 return true;
896 }
897
898 template <typename T>
AddClass(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)899 bool VariableScope::AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
900 {
901 ASSERT(newDecl->IsClassDecl());
902
903 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
904
905 if (!currentVariable) {
906 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
907 return true;
908 }
909
910 auto decl = currentVariable->Declaration();
911 if (newDecl->AsClassDecl()->IsDeclare() && decl->IsFunctionDecl()) {
912 decl->AsFunctionDecl()->SetDeclClass(newDecl->AsClassDecl());
913 return true;
914 }
915
916 return false;
917 }
918
919 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,VariableFlags flags)920 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, Decl *newDecl,
921 VariableFlags flags)
922 {
923 ASSERT(!currentVariable);
924 // TODO(xucheng): move the ts variables to tsBindings_
925 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
926 return true;
927 }
928
929 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Decl * newDecl,VariableFlags flags)930 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags)
931 {
932 switch (flags) {
933 case VariableFlags::NAMESPACE: {
934 return tsBindings_.AddTSVariable<TSBindingType::NAMESPACE>(
935 newDecl->Name(), allocator->New<T>(newDecl, flags));
936 }
937 case VariableFlags::ENUM_LITERAL: {
938 return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>(
939 newDecl->Name(), allocator->New<T>(newDecl, flags));
940 }
941 case VariableFlags::INTERFACE: {
942 return tsBindings_.AddTSVariable<TSBindingType::INTERFACE>(
943 newDecl->Name(), allocator->New<T>(newDecl, flags));
944 }
945 case VariableFlags::IMPORT_EQUALS: {
946 return tsBindings_.AddTSVariable<TSBindingType::IMPORT_EQUALS>(
947 newDecl->Name(), allocator->New<T>(newDecl, flags));
948 }
949 default: {
950 break;
951 }
952 }
953 return false;
954 }
955
956 template <typename T>
AddLexical(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)957 bool VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
958 {
959 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
960
961 if (currentVariable) {
962 return false;
963 }
964
965 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
966 return true;
967 }
968
969 template <typename T, typename... Args>
NewDecl(ArenaAllocator * allocator,Args &&...args)970 T *Scope::NewDecl(ArenaAllocator *allocator, Args &&... args)
971 {
972 T *decl = allocator->New<T>(std::forward<Args>(args)...);
973 decls_.push_back(decl);
974
975 return decl;
976 }
977
978 template <typename DeclType, typename VariableType>
AddDecl(ArenaAllocator * allocator,util::StringView name,VariableFlags flags)979 VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags)
980 {
981 if (FindLocal(name)) {
982 return nullptr;
983 }
984
985 auto *decl = allocator->New<DeclType>(name);
986 auto *variable = allocator->New<VariableType>(decl, flags);
987
988 decls_.push_back(decl);
989 bindings_.insert({decl->Name(), variable});
990
991 return variable;
992 }
993
994 template <typename DeclType, typename VariableType>
CreateVar(ArenaAllocator * allocator,util::StringView name,VariableFlags flags,const ir::AstNode * node)995 VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
996 const ir::AstNode *node)
997 {
998 auto *decl = allocator->New<DeclType>(name);
999 auto *variable = allocator->New<VariableType>(decl, flags);
1000 decl->BindNode(node);
1001 return variable;
1002 }
1003
1004 template <typename T, typename... Args>
PropagateBinding(ArenaAllocator * allocator,util::StringView name,Args &&...args)1005 void Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args)
1006 {
1007 auto res = bindings_.find(name);
1008 if (res == bindings_.end()) {
1009 bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)});
1010 return;
1011 }
1012
1013 if (!res->second->Declaration()->IsParameterDecl()) {
1014 res->second->Reset(std::forward<Args>(args)...);
1015 }
1016 }
1017
1018 } // namespace panda::es2panda::binder
1019
1020 #endif
1021