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