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 template <TSBindingType type>
FindLocalTSVariable(const util::StringView & name)326 Variable *FindLocalTSVariable(const util::StringView &name) const
327 {
328 return tsBindings_.FindTSVariable<type>(name);
329 }
330
331 template <TSBindingType type>
AddLocalTSVariable(const util::StringView & name,Variable * var)332 void AddLocalTSVariable(const util::StringView &name, Variable *var)
333 {
334 tsBindings_.AddTSVariable<type>(name, var);
335 }
336
InLocalTSBindings(const util::StringView & name)337 bool InLocalTSBindings(const util::StringView &name) const
338 {
339 return tsBindings_.InTSBindings(name);
340 }
341
342 protected:
Scope(ArenaAllocator * allocator,Scope * parent)343 explicit Scope(ArenaAllocator *allocator, Scope *parent)
344 : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()), tsBindings_(allocator)
345 {
346 }
347
348 /**
349 * @return true - if the variable is shadowed
350 * false - otherwise
351 */
352 using VariableVisitior = std::function<bool(const Variable *)>;
353
354 /**
355 * @return true - if the variable is shadowed
356 * false - otherwise
357 */
358 std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor);
359
360 bool AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
361 [[maybe_unused]] ScriptExtension extension);
362
363 Scope *parent_ {};
364 ArenaVector<Decl *> decls_;
365 VariableMap bindings_;
366 TSBindings tsBindings_;
367 ir::AstNode *node_ {};
368 const compiler::IRNode *startIns_ {};
369 const compiler::IRNode *endIns_ {};
370 };
371
372 class VariableScope : public Scope {
373 public:
374 ~VariableScope() override = default;
375 NO_COPY_SEMANTIC(VariableScope);
376 NO_MOVE_SEMANTIC(VariableScope);
377
AddFlag(VariableScopeFlags flag)378 void AddFlag(VariableScopeFlags flag)
379 {
380 flags_ |= flag;
381 }
382
ClearFlag(VariableScopeFlags flag)383 void ClearFlag(VariableScopeFlags flag)
384 {
385 flags_ &= ~flag;
386 }
387
HasFlag(VariableScopeFlags flag)388 bool HasFlag(VariableScopeFlags flag) const
389 {
390 return (flags_ & flag) != 0;
391 }
392
NextSlot()393 uint32_t NextSlot()
394 {
395 return slotIndex_++;
396 }
397
LexicalSlots()398 uint32_t LexicalSlots() const
399 {
400 return slotIndex_;
401 }
402
NeedLexEnv()403 bool NeedLexEnv() const
404 {
405 return slotIndex_ != 0;
406 }
407
AddLexicalVarNameAndType(uint32_t slot,util::StringView name,int type)408 void AddLexicalVarNameAndType(uint32_t slot, util::StringView name, int type)
409 {
410 lexicalVarNameAndTypes_.emplace(slot, std::pair<util::StringView, int>(name, type));
411 }
412
GetLexicalVarNameAndTypes()413 ArenaMap<uint32_t, std::pair<util::StringView, int>> &GetLexicalVarNameAndTypes()
414 {
415 return lexicalVarNameAndTypes_;
416 }
417
418 protected:
VariableScope(ArenaAllocator * allocator,Scope * parent)419 explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent),
420 lexicalVarNameAndTypes_(allocator->Adapter()) {}
421
422 inline VariableFlags DeclFlagToVariableFlag(DeclarationFlags declFlag);
423
424 template <typename T>
425 bool AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
426
427 template <typename T>
428 bool AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
429 [[maybe_unused]] ScriptExtension extension);
430
431 template <typename T>
432 bool AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
433
434 template <typename T>
435 bool AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
436
437 template <typename T>
438 bool AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags);
439
440 template <typename T>
441 bool AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
442
443 VariableScopeFlags flags_ {};
444 uint32_t slotIndex_ {};
445 ArenaMap<uint32_t, std::pair<util::StringView, int>> lexicalVarNameAndTypes_; // for debuginfo and patchFix
446 };
447
448 class ParamScope : public Scope {
449 public:
Type()450 ScopeType Type() const override
451 {
452 return ScopeType::PARAM;
453 }
454
Params()455 ArenaVector<LocalVariable *> &Params()
456 {
457 return params_;
458 }
459
Params()460 const ArenaVector<LocalVariable *> &Params() const
461 {
462 return params_;
463 }
464
HasParam(util::StringView name)465 bool HasParam(util::StringView name) const
466 {
467 for (auto *param : params_) {
468 if (param->Name() == name) {
469 return true;
470 }
471 }
472
473 return false;
474 }
475
476 std::tuple<ParameterDecl *, const ir::AstNode *> AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param);
477
478 protected:
ParamScope(ArenaAllocator * allocator,Scope * parent)479 explicit ParamScope(ArenaAllocator *allocator, Scope *parent)
480 : Scope(allocator, parent), params_(allocator->Adapter())
481 {
482 }
483
484 bool AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
485
486 ArenaVector<LocalVariable *> params_;
487 };
488
489 class FunctionScope;
490
491 class FunctionParamScope : public ParamScope {
492 public:
FunctionParamScope(ArenaAllocator * allocator,Scope * parent)493 explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
494
GetFunctionScope()495 FunctionScope *GetFunctionScope() const
496 {
497 return functionScope_;
498 }
499
BindFunctionScope(FunctionScope * funcScope)500 void BindFunctionScope(FunctionScope *funcScope)
501 {
502 functionScope_ = funcScope;
503 }
504
NameVar()505 LocalVariable *NameVar() const
506 {
507 return nameVar_;
508 }
509
510 void BindName(ArenaAllocator *allocator, util::StringView name);
511
Type()512 ScopeType Type() const override
513 {
514 return ScopeType::FUNCTION_PARAM;
515 }
516
517 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
518 [[maybe_unused]] ScriptExtension extension) override;
519
RemoveThisParam(const std::string_view & thisParam)520 void RemoveThisParam(const std::string_view &thisParam)
521 {
522 params_.erase(params_.begin());
523 bindings_.erase(thisParam);
524 }
525
526 friend class FunctionScope;
527 template <typename E, typename T>
528 friend class ScopeWithParamScope;
529
530 private:
531 FunctionScope *functionScope_ {};
532 LocalVariable *nameVar_ {};
533 };
534
535 template <typename E, typename T>
536 class ScopeWithParamScope : public E {
537 public:
ScopeWithParamScope(ArenaAllocator * allocator,Scope * parent)538 explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent) {}
539
BindParamScope(T * paramScope)540 void BindParamScope(T *paramScope)
541 {
542 AssignParamScope(paramScope);
543 this->bindings_ = paramScope->Bindings();
544 }
545
AssignParamScope(T * paramScope)546 void AssignParamScope(T *paramScope)
547 {
548 ASSERT(this->parent_ == paramScope);
549 ASSERT(this->bindings_.empty());
550
551 paramScope_ = paramScope;
552 }
553
ParamScope()554 T *ParamScope()
555 {
556 return paramScope_;
557 }
558
ParamScope()559 const T *ParamScope() const
560 {
561 return paramScope_;
562 }
563
AddBindsFromParam()564 void AddBindsFromParam()
565 {
566 ASSERT(paramScope_);
567 this->bindings_.insert(paramScope_->Bindings().begin(), paramScope_->Bindings().end());
568 }
569
570 protected:
571 T *paramScope_;
572 };
573
574 class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> {
575 public:
FunctionScope(ArenaAllocator * allocator,Scope * parent)576 explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
577
Type()578 ScopeType Type() const override
579 {
580 return ScopeType::FUNCTION;
581 }
582
BindName(util::StringView name,util::StringView internalName)583 void BindName(util::StringView name, util::StringView internalName)
584 {
585 name_ = name;
586 internalName_ = internalName;
587 }
588
Name()589 const util::StringView &Name() const
590 {
591 return name_;
592 }
593
InternalName()594 const util::StringView &InternalName() const
595 {
596 return internalName_;
597 }
598
InFunctionScopes()599 bool InFunctionScopes() const
600 {
601 return inFunctionScopes_;
602 }
603
SetInFunctionScopes()604 void SetInFunctionScopes()
605 {
606 inFunctionScopes_ = true;
607 }
608
609 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
610 [[maybe_unused]] ScriptExtension extension) override;
611
612 private:
613 util::StringView name_ {};
614 util::StringView internalName_ {};
615 bool inFunctionScopes_ {false};
616 };
617
618 class LocalScope : public Scope {
619 public:
LocalScope(ArenaAllocator * allocator,Scope * parent)620 explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
621
Type()622 ScopeType Type() const override
623 {
624 return ScopeType::LOCAL;
625 }
626
627 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
628 [[maybe_unused]] ScriptExtension extension) override;
629 };
630
631 class CatchParamScope : public ParamScope {
632 public:
CatchParamScope(ArenaAllocator * allocator,Scope * parent)633 explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
634
Type()635 ScopeType Type() const override
636 {
637 return ScopeType::CATCH_PARAM;
638 }
639
640 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
641 [[maybe_unused]] ScriptExtension extension) override;
642
643 friend class CatchScope;
644 };
645
646 class CatchScope : public ScopeWithParamScope<LocalScope, CatchParamScope> {
647 public:
CatchScope(ArenaAllocator * allocator,Scope * parent)648 explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
649
Type()650 ScopeType Type() const override
651 {
652 return ScopeType::CATCH;
653 }
654
655 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
656 [[maybe_unused]] ScriptExtension extension) override;
657 };
658
659 class LoopScope : public VariableScope {
660 public:
LoopScope(ArenaAllocator * allocator,Scope * parent)661 explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
662
Type()663 ScopeType Type() const override
664 {
665 return loopType_;
666 }
667
668 void InitVariable();
669
AddBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)670 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
671 [[maybe_unused]] ScriptExtension extension) override
672 {
673 return AddLocal(allocator, currentVariable, newDecl, extension);
674 }
675
676 protected:
677 ScopeType loopType_ {ScopeType::LOOP};
678 };
679
680 class GlobalScope : public FunctionScope {
681 public:
GlobalScope(ArenaAllocator * allocator)682 explicit GlobalScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
683 {
684 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
685 }
686
Type()687 ScopeType Type() const override
688 {
689 return ScopeType::GLOBAL;
690 }
691
692 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
693 [[maybe_unused]] ScriptExtension extension) override;
694 };
695
696 class ModuleScope : public FunctionScope {
697 public:
ModuleScope(ArenaAllocator * allocator)698 explicit ModuleScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr)
699 {
700 paramScope_ = allocator->New<FunctionParamScope>(allocator, this);
701 }
702
Type()703 ScopeType Type() const override
704 {
705 return ScopeType::MODULE;
706 }
707
708 void AssignIndexToModuleVariable(util::StringView name, uint32_t index);
709
710 void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName);
711
712 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
713 [[maybe_unused]] ScriptExtension extension) override;
714 };
715
716 class TSModuleScope : public FunctionScope {
717 public:
TSModuleScope(ArenaAllocator * allocator,Scope * parent,ExportBindings * exportBindings)718 explicit TSModuleScope(ArenaAllocator *allocator, Scope *parent, ExportBindings *exportBindings)
719 : FunctionScope(allocator, nullptr), exportBindings_(exportBindings), variableNames_(allocator->Adapter())
720 {
721 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
722 paramScope_->BindFunctionScope(this);
723 SetParent(paramScope_);
724 }
725
Type()726 ScopeType Type() const override
727 {
728 return ScopeType::TSMODULE;
729 }
730
731 template <TSBindingType type>
FindExportTSVariable(const util::StringView & name)732 Variable *FindExportTSVariable(const util::StringView &name) const
733 {
734 return exportBindings_->FindExportTSVariable<type>(name);
735 }
736
737 template <TSBindingType type>
AddExportTSVariable(const util::StringView & name,Variable * var)738 bool AddExportTSVariable(const util::StringView &name, Variable *var)
739 {
740 return exportBindings_->AddExportTSVariable<type>(name, var);
741 }
742
FindExportVariable(const util::StringView & name)743 Variable *FindExportVariable(const util::StringView &name) const
744 {
745 return exportBindings_->FindExportVariable(name);
746 }
747
AddExportVariable(const util::StringView & name,Variable * var)748 bool AddExportVariable(const util::StringView &name, Variable *var)
749 {
750 return exportBindings_->AddExportVariable(name, var);
751 }
752
AddExportVariable(const util::StringView & name)753 bool AddExportVariable(const util::StringView &name)
754 {
755 return exportBindings_->AddExportVariable(name, FindLocal(name));
756 }
757
InExportBindings(const util::StringView & name)758 bool InExportBindings(const util::StringView &name) const
759 {
760 return exportBindings_->InExportBindings(name);
761 }
762
AddDeclarationName(const util::StringView & name)763 void AddDeclarationName(const util::StringView &name)
764 {
765 variableNames_.insert(name);
766 }
767
HasVariableName(const util::StringView & name)768 bool HasVariableName(const util::StringView &name) const
769 {
770 return variableNames_.find(name) != variableNames_.end();
771 }
772
773 private:
774 ExportBindings *exportBindings_;
775 ArenaSet<util::StringView> variableNames_;
776 };
777
778 class TSEnumScope : public FunctionScope {
779 public:
TSEnumScope(ArenaAllocator * allocator,Scope * parent,VariableMap * enumMemberBindings)780 explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope(
781 allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter())
782 {
783 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent);
784 paramScope_->BindFunctionScope(this);
785 SetParent(paramScope_);
786 }
787
Type()788 ScopeType Type() const override
789 {
790 return ScopeType::TSENUM;
791 }
792
FindEnumMemberVariable(const util::StringView & name)793 Variable *FindEnumMemberVariable(const util::StringView &name) const
794 {
795 auto res = enumMemberBindings_->find(name);
796 if (res == enumMemberBindings_->end()) {
797 return nullptr;
798 }
799 return res->second;
800 }
801
AddDeclarationName(const util::StringView & name)802 void AddDeclarationName(const util::StringView &name)
803 {
804 variableNames_.insert(name);
805 }
806
HasDeclarationName(const util::StringView & name)807 bool HasDeclarationName(const util::StringView &name) const
808 {
809 return variableNames_.find(name) != variableNames_.end();
810 }
811
812 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
813 [[maybe_unused]] ScriptExtension extension) override;
814
815 private:
816 VariableMap *enumMemberBindings_;
817 ArenaSet<util::StringView> variableNames_;
818 };
819
DeclFlagToVariableFlag(DeclarationFlags declFlag)820 inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag)
821 {
822 VariableFlags varFlag = VariableFlags::NONE;
823 if (declFlag & DeclarationFlags::EXPORT) {
824 varFlag = VariableFlags::LOCAL_EXPORT;
825 } else if (declFlag & DeclarationFlags::IMPORT) {
826 varFlag = VariableFlags::IMPORT;
827 }
828 return varFlag;
829 }
830
831 template <typename T>
AddVar(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)832 bool VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
833 {
834 VariableFlags flags = VariableFlags::HOIST_VAR;
835 flags |= DeclFlagToVariableFlag(newDecl->Flags());
836
837 if (!currentVariable) {
838 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
839 return true;
840 }
841
842 switch (currentVariable->Declaration()->Type()) {
843 case DeclType::VAR: {
844 currentVariable->Reset(newDecl, flags);
845 break;
846 }
847 case DeclType::PARAM:
848 case DeclType::FUNC: {
849 break;
850 }
851 default: {
852 return false;
853 }
854 }
855
856 return true;
857 }
858
859 template <typename T>
AddFunction(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,ScriptExtension extension)860 bool VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
861 [[maybe_unused]] ScriptExtension extension)
862 {
863 VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST;
864 flags |= DeclFlagToVariableFlag(newDecl->Flags());
865
866 if (!currentVariable) {
867 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
868 return true;
869 }
870
871 auto decl = currentVariable->Declaration();
872 if (decl->IsClassDecl() && decl->AsClassDecl()->IsDeclare()) {
873 newDecl->AsFunctionDecl()->SetDeclClass(decl->AsClassDecl());
874 bindings_[newDecl->Name()] = allocator->New<T>(newDecl, flags);
875 return true;
876 }
877
878 if (extension != ScriptExtension::JS) {
879 return false;
880 }
881
882 switch (currentVariable->Declaration()->Type()) {
883 case DeclType::VAR:
884 case DeclType::FUNC: {
885 currentVariable->Reset(newDecl, flags);
886 break;
887 }
888 default: {
889 return false;
890 }
891 }
892
893 return true;
894 }
895
896 template <typename T>
AddClass(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)897 bool VariableScope::AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
898 {
899 ASSERT(newDecl->IsClassDecl());
900
901 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
902
903 if (!currentVariable) {
904 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
905 return true;
906 }
907
908 auto decl = currentVariable->Declaration();
909 if (newDecl->AsClassDecl()->IsDeclare() && decl->IsFunctionDecl()) {
910 decl->AsFunctionDecl()->SetDeclClass(newDecl->AsClassDecl());
911 return true;
912 }
913
914 return false;
915 }
916
917 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl,VariableFlags flags)918 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, Decl *newDecl,
919 VariableFlags flags)
920 {
921 ASSERT(!currentVariable);
922 // TODO(xucheng): move the ts variables to tsBindings_
923 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
924 return true;
925 }
926
927 template <typename T>
AddTSBinding(ArenaAllocator * allocator,Decl * newDecl,VariableFlags flags)928 bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags)
929 {
930 switch (flags) {
931 case VariableFlags::NAMESPACE: {
932 return tsBindings_.AddTSVariable<TSBindingType::NAMESPACE>(
933 newDecl->Name(), allocator->New<T>(newDecl, flags));
934 }
935 case VariableFlags::ENUM_LITERAL: {
936 return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>(
937 newDecl->Name(), allocator->New<T>(newDecl, flags));
938 }
939 case VariableFlags::INTERFACE: {
940 return tsBindings_.AddTSVariable<TSBindingType::INTERFACE>(
941 newDecl->Name(), allocator->New<T>(newDecl, flags));
942 }
943 case VariableFlags::IMPORT_EQUALS: {
944 return tsBindings_.AddTSVariable<TSBindingType::IMPORT_EQUALS>(
945 newDecl->Name(), allocator->New<T>(newDecl, flags));
946 }
947 default: {
948 break;
949 }
950 }
951 return false;
952 }
953
954 template <typename T>
AddLexical(ArenaAllocator * allocator,Variable * currentVariable,Decl * newDecl)955 bool VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
956 {
957 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags());
958
959 if (currentVariable) {
960 return false;
961 }
962
963 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)});
964 return true;
965 }
966
967 template <typename T, typename... Args>
NewDecl(ArenaAllocator * allocator,Args &&...args)968 T *Scope::NewDecl(ArenaAllocator *allocator, Args &&... args)
969 {
970 T *decl = allocator->New<T>(std::forward<Args>(args)...);
971 decls_.push_back(decl);
972
973 return decl;
974 }
975
976 template <typename DeclType, typename VariableType>
AddDecl(ArenaAllocator * allocator,util::StringView name,VariableFlags flags)977 VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags)
978 {
979 if (FindLocal(name)) {
980 return nullptr;
981 }
982
983 auto *decl = allocator->New<DeclType>(name);
984 auto *variable = allocator->New<VariableType>(decl, flags);
985
986 decls_.push_back(decl);
987 bindings_.insert({decl->Name(), variable});
988
989 return variable;
990 }
991
992 template <typename DeclType, typename VariableType>
CreateVar(ArenaAllocator * allocator,util::StringView name,VariableFlags flags,const ir::AstNode * node)993 VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
994 const ir::AstNode *node)
995 {
996 auto *decl = allocator->New<DeclType>(name);
997 auto *variable = allocator->New<VariableType>(decl, flags);
998 decl->BindNode(node);
999 return variable;
1000 }
1001
1002 template <typename T, typename... Args>
PropagateBinding(ArenaAllocator * allocator,util::StringView name,Args &&...args)1003 void Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args)
1004 {
1005 auto res = bindings_.find(name);
1006 if (res == bindings_.end()) {
1007 bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)});
1008 return;
1009 }
1010
1011 if (!res->second->Declaration()->IsParameterDecl()) {
1012 res->second->Reset(std::forward<Args>(args)...);
1013 }
1014 }
1015
1016 } // namespace panda::es2panda::binder
1017
1018 #endif
1019