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