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