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