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