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
ScopeStart()237 const compiler::IRNode *ScopeStart() const
238 {
239 return startIns_;
240 }
241
ScopeEnd()242 const compiler::IRNode *ScopeEnd() const
243 {
244 return endIns_;
245 }
246
SetScopeStart(const compiler::IRNode * ins)247 void SetScopeStart(const compiler::IRNode *ins)
248 {
249 startIns_ = ins;
250 }
251
SetScopeEnd(const compiler::IRNode * ins)252 void SetScopeEnd(const compiler::IRNode *ins)
253 {
254 endIns_ = ins;
255 }
256
Node()257 const ir::AstNode *Node() const
258 {
259 return node_;
260 }
261
BindNode(const ir::AstNode * node)262 void BindNode(const ir::AstNode *node)
263 {
264 node_ = node;
265 }
266
AddDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)267 bool AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
268 {
269 decls_.push_back(decl);
270 return AddBinding(allocator, FindLocal(decl->Name()), decl, extension);
271 }
272
AddTsDecl(ArenaAllocator * allocator,Decl * decl,ScriptExtension extension)273 bool AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
274 {
275 decls_.push_back(decl);
276 return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension);
277 }
278
279 template <typename T, typename... Args>
280 T *NewDecl(ArenaAllocator *allocator, Args &&... args);
281
282 template <typename DeclType, typename VariableType>
283 VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags);
284
285 template <typename DeclType = binder::LetDecl, typename VariableType = binder::LocalVariable>
286 static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
287 const ir::AstNode *node);
288
289 template <typename T, typename... Args>
290 void PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args);
291
Bindings()292 VariableMap &Bindings()
293 {
294 return bindings_;
295 }
296
Bindings()297 const VariableMap &Bindings() const
298 {
299 return bindings_;
300 }
301
302 virtual bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
303 [[maybe_unused]] ScriptExtension extension) = 0;
304
305 Variable *FindLocal(const util::StringView &name,
306 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
307
308 ScopeFindResult Find(const util::StringView &name,
309 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
310
311 Decl *FindDecl(const util::StringView &name) const;
312
313 bool HasVarDecl(const util::StringView &name) const;
314
315 template <TSBindingType type>
FindLocalTSVariable(const util::StringView & name)316 Variable *FindLocalTSVariable(const util::StringView &name) const
317 {
318 return tsBindings_.FindTSVariable<type>(name);
319 }
320
321 template <TSBindingType type>
AddLocalTSVariable(const util::StringView & name,Variable * var)322 void AddLocalTSVariable(const util::StringView &name, Variable *var)
323 {
324 tsBindings_.AddTSVariable<type>(name, var);
325 }
326
InLocalTSBindings(const util::StringView & name)327 bool InLocalTSBindings(const util::StringView &name) const
328 {
329 return tsBindings_.InTSBindings(name);
330 }
331
332 protected:
Scope(ArenaAllocator * allocator,Scope * parent)333 explicit Scope(ArenaAllocator *allocator, Scope *parent)
334 : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()), tsBindings_(allocator)
335 {
336 }
337
338 /**
339 * @return true - if the variable is shadowed
340 * false - otherwise
341 */
342 using VariableVisitior = std::function<bool(const Variable *)>;
343
344 /**
345 * @return true - if the variable is shadowed
346 * false - otherwise
347 */
348 std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor);
349
350 bool AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
351 [[maybe_unused]] ScriptExtension extension);
352
SetParent(Scope * parent)353 void SetParent(Scope *parent)
354 {
355 parent_ = parent;
356 }
357
358 Scope *parent_ {};
359 ArenaVector<Decl *> decls_;
360 VariableMap bindings_;
361 TSBindings tsBindings_;
362 const ir::AstNode *node_ {};
363 const compiler::IRNode *startIns_ {};
364 const compiler::IRNode *endIns_ {};
365 };
366
367 class VariableScope : public Scope {
368 public:
369 ~VariableScope() override = default;
370 NO_COPY_SEMANTIC(VariableScope);
371 NO_MOVE_SEMANTIC(VariableScope);
372
AddFlag(VariableScopeFlags flag)373 void AddFlag(VariableScopeFlags flag)
374 {
375 flags_ |= flag;
376 }
377
ClearFlag(VariableScopeFlags flag)378 void ClearFlag(VariableScopeFlags flag)
379 {
380 flags_ &= ~flag;
381 }
382
HasFlag(VariableScopeFlags flag)383 bool HasFlag(VariableScopeFlags flag) const
384 {
385 return (flags_ & flag) != 0;
386 }
387
NextSlot()388 uint32_t NextSlot()
389 {
390 return slotIndex_++;
391 }
392
LexicalSlots()393 uint32_t LexicalSlots() const
394 {
395 return slotIndex_;
396 }
397
NeedLexEnv()398 bool NeedLexEnv() const
399 {
400 return slotIndex_ != 0;
401 }
402
AddLexicalVarNameAndType(uint32_t slot,util::StringView name,int type)403 void AddLexicalVarNameAndType(uint32_t slot, util::StringView name, int type)
404 {
405 lexicalVarNameAndTypes_.emplace(slot, std::pair<util::StringView, int>(name, type));
406 }
407
GetLexicalVarNameAndTypes()408 ArenaMap<uint32_t, std::pair<util::StringView, int>> &GetLexicalVarNameAndTypes()
409 {
410 return lexicalVarNameAndTypes_;
411 }
412
413 protected:
VariableScope(ArenaAllocator * allocator,Scope * parent)414 explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent),
415 lexicalVarNameAndTypes_(allocator->Adapter()) {}
416
417 inline VariableFlags DeclFlagToVariableFlag(DeclarationFlags declFlag);
418
419 template <typename T>
420 bool AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
421
422 template <typename T>
423 bool AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
424 [[maybe_unused]] ScriptExtension extension);
425
426 template <typename T>
427 bool AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
428
429 template <typename T>
430 bool AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags);
431
432 template <typename T>
433 bool AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
434
435 VariableScopeFlags flags_ {};
436 uint32_t slotIndex_ {};
437 ArenaMap<uint32_t, std::pair<util::StringView, int>> lexicalVarNameAndTypes_; // for debuginfo and hotfix
438 };
439
440 class ParamScope : public Scope {
441 public:
Type()442 ScopeType Type() const override
443 {
444 return ScopeType::PARAM;
445 }
446
Params()447 ArenaVector<LocalVariable *> &Params()
448 {
449 return params_;
450 }
451
Params()452 const ArenaVector<LocalVariable *> &Params() const
453 {
454 return params_;
455 }
456
HasParam(util::StringView name)457 bool HasParam(util::StringView name) const
458 {
459 for (auto *param : params_) {
460 if (param->Name() == name) {
461 return true;
462 }
463 }
464
465 return false;
466 }
467
468 std::tuple<ParameterDecl *, const ir::AstNode *> AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param);
469
470 protected:
ParamScope(ArenaAllocator * allocator,Scope * parent)471 explicit ParamScope(ArenaAllocator *allocator, Scope *parent)
472 : Scope(allocator, parent), params_(allocator->Adapter())
473 {
474 }
475
476 bool AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
477
478 ArenaVector<LocalVariable *> params_;
479 };
480
481 class FunctionScope;
482
483 class FunctionParamScope : public ParamScope {
484 public:
FunctionParamScope(ArenaAllocator * allocator,Scope * parent)485 explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
486
GetFunctionScope()487 FunctionScope *GetFunctionScope() const
488 {
489 return functionScope_;
490 }
491
BindFunctionScope(FunctionScope * funcScope)492 void BindFunctionScope(FunctionScope *funcScope)
493 {
494 functionScope_ = funcScope;
495 }
496
NameVar()497 LocalVariable *NameVar() const
498 {
499 return nameVar_;
500 }
501
502 void BindName(ArenaAllocator *allocator, util::StringView name);
503
Type()504 ScopeType Type() const override
505 {
506 return ScopeType::FUNCTION_PARAM;
507 }
508
509 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
510 [[maybe_unused]] ScriptExtension extension) override;
511
RemoveThisParam()512 void RemoveThisParam()
513 {
514 params_.erase(params_.begin());
515 }
516
517 friend class FunctionScope;
518 template <typename E, typename T>
519 friend class ScopeWithParamScope;
520
521 private:
522 FunctionScope *functionScope_ {};
523 LocalVariable *nameVar_ {};
524 };
525
526 template <typename E, typename T>
527 class ScopeWithParamScope : public E {
528 public:
ScopeWithParamScope(ArenaAllocator * allocator,Scope * parent)529 explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent) {}
530
BindParamScope(T * paramScope)531 void BindParamScope(T *paramScope)
532 {
533 AssignParamScope(paramScope);
534 this->bindings_ = paramScope->Bindings();
535 }
536
AssignParamScope(T * paramScope)537 void AssignParamScope(T *paramScope)
538 {
539 ASSERT(this->parent_ == paramScope);
540 ASSERT(this->bindings_.empty());
541
542 paramScope_ = paramScope;
543 }
544
ParamScope()545 T *ParamScope()
546 {
547 return paramScope_;
548 }
549
ParamScope()550 const T *ParamScope() const
551 {
552 return paramScope_;
553 }
554
AddBindsFromParam()555 void AddBindsFromParam()
556 {
557 ASSERT(paramScope_);
558 this->bindings_.insert(paramScope_->Bindings().begin(), paramScope_->Bindings().end());
559 }
560
561 protected:
562 T *paramScope_;
563 };
564
565 class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> {
566 public:
FunctionScope(ArenaAllocator * allocator,Scope * parent)567 explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
568
Type()569 ScopeType Type() const override
570 {
571 return ScopeType::FUNCTION;
572 }
573
BindName(util::StringView name,util::StringView internalName)574 void BindName(util::StringView name, util::StringView internalName)
575 {
576 name_ = name;
577 internalName_ = internalName;
578 }
579
Name()580 const util::StringView &Name() const
581 {
582 return name_;
583 }
584
InternalName()585 const util::StringView &InternalName() const
586 {
587 return internalName_;
588 }
589
590 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
591 [[maybe_unused]] ScriptExtension extension) override;
592
593 private:
594 util::StringView name_ {};
595 util::StringView internalName_ {};
596 };
597
598 class LocalScope : public Scope {
599 public:
LocalScope(ArenaAllocator * allocator,Scope * parent)600 explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
601
Type()602 ScopeType Type() const override
603 {
604 return ScopeType::LOCAL;
605 }
606
607 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
608 [[maybe_unused]] ScriptExtension extension) override;
609 };
610
611 class CatchParamScope : public ParamScope {
612 public:
CatchParamScope(ArenaAllocator * allocator,Scope * parent)613 explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
614
Type()615 ScopeType Type() const override
616 {
617 return ScopeType::CATCH_PARAM;
618 }
619
620 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
621 [[maybe_unused]] ScriptExtension extension) override;
622
623 friend class CatchScope;
624 };
625
626 class CatchScope : public ScopeWithParamScope<LocalScope, CatchParamScope> {
627 public:
CatchScope(ArenaAllocator * allocator,Scope * parent)628 explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
629
Type()630 ScopeType Type() const override
631 {
632 return ScopeType::CATCH;
633 }
634
635 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
636 [[maybe_unused]] ScriptExtension extension) override;
637 };
638
639 class LoopScope : public VariableScope {
640 public:
LoopScope(ArenaAllocator * allocator,Scope * parent)641 explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
642
Type()643 ScopeType Type() const override
644 {
645 return loopType_;
646 }
647
648 void InitVariable();
649
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)650 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
651 [[maybe_unused]] ScriptExtension extension) override
652 {
653 return AddLocal(allocator, currentVariable, newDecl, extension);
654 }
655
656 protected:
657 ScopeType loopType_ {ScopeType::LOOP};
658 };
659
660 class GlobalScope : public FunctionScope {
661 public:
GlobalScope(ArenaAllocator * allocator)662 explicit GlobalScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
663 {
664 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
665 }
666
Type()667 ScopeType Type() const override
668 {
669 return ScopeType::GLOBAL;
670 }
671
672 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
673 [[maybe_unused]] ScriptExtension extension) override;
674 };
675
676 class ModuleScope : public FunctionScope {
677 public:
ModuleScope(ArenaAllocator * allocator)678 explicit ModuleScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
679 {
680 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
681 }
682
Type()683 ScopeType Type() const override
684 {
685 return ScopeType::MODULE;
686 }
687
688 void AssignIndexToModuleVariable(util::StringView name, uint32_t index);
689
690 void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName);
691
692 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
693 [[maybe_unused]] ScriptExtension extension) override;
694 };
695
696 class TSModuleScope : public FunctionScope {
697 public:
TSModuleScope(ArenaAllocator * allocator,Scope * parent,ExportBindings * exportBindings)698 explicit TSModuleScope(ArenaAllocator *allocator, Scope *parent, ExportBindings *exportBindings)
699 : FunctionScope(allocator, nullptr), exportBindings_(exportBindings), variableNames_(allocator->Adapter())
700 {
701 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
702 paramScope_->BindFunctionScope(this);
703 SetParent(paramScope_);
704 }
705
Type()706 ScopeType Type() const override
707 {
708 return ScopeType::TSMODULE;
709 }
710
711 template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)712 Variable *FindExportTSVariable(const util::StringView &name) const
713 {
714 return exportBindings_->FindExportTSVariable<type>(name);
715 }
716
717 template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)718 bool AddExportTSVariable(const util::StringView &name, Variable *var)
719 {
720 return exportBindings_->AddExportTSVariable<type>(name, var);
721 }
722
FindExportVariable(const util::StringView & name)723 Variable *FindExportVariable(const util::StringView &name) const
724 {
725 return exportBindings_->FindExportVariable(name);
726 }
727
AddExportVariable(const util::StringView & name,Variable * var)728 bool AddExportVariable(const util::StringView &name, Variable *var)
729 {
730 return exportBindings_->AddExportVariable(name, var);
731 }
732
AddExportVariable(const util::StringView & name)733 bool AddExportVariable(const util::StringView &name)
734 {
735 return exportBindings_->AddExportVariable(name, FindLocal(name));
736 }
737
InExportBindings(const util::StringView & name)738 bool InExportBindings(const util::StringView &name) const
739 {
740 return exportBindings_->InExportBindings(name);
741 }
742
AddDeclarationName(const util::StringView & name)743 void AddDeclarationName(const util::StringView &name)
744 {
745 variableNames_.insert(name);
746 }
747
HasVariableName(const util::StringView & name)748 bool HasVariableName(const util::StringView &name) const
749 {
750 return variableNames_.find(name) != variableNames_.end();
751 }
752
753 private:
754 ExportBindings *exportBindings_;
755 ArenaSet<util::StringView> variableNames_;
756 };
757
DeclFlagToVariableFlag(DeclarationFlags declFlag)758 inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag)
759 {
760 VariableFlags varFlag = VariableFlags::NONE;
761 if (declFlag & DeclarationFlags::EXPORT) {
762 varFlag = VariableFlags::LOCAL_EXPORT;
763 } else if (declFlag & DeclarationFlags::IMPORT) {
764 varFlag = VariableFlags::IMPORT;
765 }
766 return varFlag;
767 }
768
769 template <typename T>
AddVar(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)770 bool VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
771 {
772 VariableFlags flags = VariableFlags::HOIST_VAR;
773 flags |= DeclFlagToVariableFlag(newDecl->Flags());
774
775 if (!currentVariable) {
776 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
777 return true;
778 }
779
780 switch (currentVariable->Declaration()->Type()) {
781 case DeclType::VAR: {
782 currentVariable->Reset(newDecl, flags);
783 break;
784 }
785 case DeclType::PARAM:
786 case DeclType::FUNC: {
787 break;
788 }
789 default: {
790 return false;
791 }
792 }
793
794 return true;
795 }
796
797 template <typename T>
AddFunction(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)798 bool VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
799 [[maybe_unused]] ScriptExtension extension)
800 {
801 VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST;
802 flags |= DeclFlagToVariableFlag(newDecl->Flags());
803
804 if (!currentVariable) {
805 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
806 return true;
807 }
808
809 if (extension != ScriptExtension::JS) {
810 return false;
811 }
812
813 switch (currentVariable->Declaration()->Type()) {
814 case DeclType::VAR:
815 case DeclType::FUNC: {
816 currentVariable->Reset(newDecl, flags);
817 break;
818 }
819 default: {
820 return false;
821 }
822 }
823
824 return true;
825 }
826
827 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,VariableFlags flags)828 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, Decl *newDecl,
829 VariableFlags flags)
830 {
831 ASSERT(!currentVariable);
832 // TODO(xucheng): move the ts variables to tsBindings_
833 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
834 return true;
835 }
836
837 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Decl * newDecl,VariableFlags flags)838 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags)
839 {
840 switch (flags) {
841 case VariableFlags::NAMESPACE: {
842 return tsBindings_.AddTSVariable<TSBindingType::NAMESPACE>(
843 newDecl->Name(), allocator->New<T>(newDecl, flags));
844 }
845 case VariableFlags::ENUM_LITERAL: {
846 return tsBindings_.AddTSVariable<TSBindingType::ENUM>(
847 newDecl->Name(), allocator->New<T>(newDecl, flags));
848 }
849 case VariableFlags::INTERFACE: {
850 return tsBindings_.AddTSVariable<TSBindingType::INTERFACE>(
851 newDecl->Name(), allocator->New<T>(newDecl, flags));
852 }
853 case VariableFlags::IMPORT_EQUALS: {
854 return tsBindings_.AddTSVariable<TSBindingType::IMPORT_EQUALS>(
855 newDecl->Name(), allocator->New<T>(newDecl, flags));
856 }
857 default: {
858 break;
859 }
860 }
861 return false;
862 }
863
864 template <typename T>
AddLexical(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)865 bool VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
866 {
867 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
868
869 if (currentVariable) {
870 return false;
871 }
872
873 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
874 return true;
875 }
876
877 template <typename T, typename... Args>
NewDecl(ArenaAllocator * allocator,Args &&...args)878 T *Scope::NewDecl(ArenaAllocator *allocator, Args &&... args)
879 {
880 T *decl = allocator->New<T>(std::forward<Args>(args)...);
881 decls_.push_back(decl);
882
883 return decl;
884 }
885
886 template <typename DeclType, typename VariableType>
AddDecl(ArenaAllocator * allocator,util::StringView name,VariableFlags flags)887 VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags)
888 {
889 if (FindLocal(name)) {
890 return nullptr;
891 }
892
893 auto *decl = allocator->New<DeclType>(name);
894 auto *variable = allocator->New<VariableType>(decl, flags);
895
896 decls_.push_back(decl);
897 bindings_.insert({decl->Name(), variable});
898
899 return variable;
900 }
901
902 template <typename DeclType, typename VariableType>
CreateVar(ArenaAllocator * allocator,util::StringView name,VariableFlags flags,const ir::AstNode * node)903 VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
904 const ir::AstNode *node)
905 {
906 auto *decl = allocator->New<DeclType>(name);
907 auto *variable = allocator->New<VariableType>(decl, flags);
908 decl->BindNode(node);
909 return variable;
910 }
911
912 template <typename T, typename... Args>
PropagateBinding(ArenaAllocator * allocator,util::StringView name,Args &&...args)913 void Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args)
914 {
915 auto res = bindings_.find(name);
916 if (res == bindings_.end()) {
917 bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)});
918 return;
919 }
920
921 if (!res->second->Declaration()->IsParameterDecl()) {
922 res->second->Reset(std::forward<Args>(args)...);
923 }
924 }
925
926 } // namespace panda::es2panda::binder
927
928 #endif
929