• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_VARBINDER_VARBINDER_H
17 #define ES2PANDA_VARBINDER_VARBINDER_H
18 
19 #include "varbinder/scope.h"
20 #include "varbinder/variableFlags.h"
21 #include "lexer/token/sourceLocation.h"
22 #include "macros.h"
23 
24 namespace ark::es2panda::parser {
25 class Program;
26 enum class ScriptKind;
27 }  // namespace ark::es2panda::parser
28 
29 namespace ark::es2panda::ir {
30 class AstNode;
31 class BlockStatement;
32 class CatchClause;
33 class ClassDefinition;
34 class Expression;
35 class ForUpdateStatement;
36 class Identifier;
37 class ScriptFunction;
38 class Statement;
39 class VariableDeclarator;
40 class TSFunctionType;
41 class ThisExpression;
42 class MemberExpression;
43 class ClassStaticBlock;
44 }  // namespace ark::es2panda::ir
45 
46 namespace ark::es2panda::public_lib {
47 struct Context;
48 }  // namespace ark::es2panda::public_lib
49 
50 namespace ark::es2panda::varbinder {
51 class ETSBinder;
52 
53 class VarBinder {
54 public:
VarBinder(ArenaAllocator * allocator)55     explicit VarBinder(ArenaAllocator *allocator) : allocator_(allocator), functionScopes_(allocator_->Adapter()) {}
56 
57     NO_COPY_SEMANTIC(VarBinder);
58     NO_MOVE_SEMANTIC(VarBinder);
59     virtual ~VarBinder() = default;
60 
61     void InitTopScope();
62     virtual void IdentifierAnalysis();
63 
64     template <typename T, typename... Args>
65     T *AddDecl(const lexer::SourcePosition &pos, Args &&...args);
66 
67     template <typename T, typename... Args>
68     T *AddTsDecl(const lexer::SourcePosition &pos, Args &&...args);
69 
70     template <typename T, typename... Args>
71     std::tuple<T *, varbinder::Variable *> NewVarDecl(const lexer::SourcePosition &pos, Args &&...args);
72 
73     std::tuple<ParameterDecl *, Variable *> AddParamDecl(ir::AstNode *param);
74 
SetProgram(parser::Program * program)75     void SetProgram(parser::Program *program)
76     {
77         program_ = program;
78     }
79 
Program()80     parser::Program *Program()
81     {
82         return program_;
83     }
84 
Program()85     const parser::Program *Program() const
86     {
87         ASSERT(program_);
88         return program_;
89     }
90 
SetContext(public_lib::Context * context)91     void SetContext(public_lib::Context *context)
92     {
93         ASSERT(!context_);
94         context_ = context;
95     }
96 
GetContext()97     public_lib::Context *GetContext() const
98     {
99         ASSERT(context_);
100         return context_;
101     }
102 
SetGenStdLib(bool genStdLib)103     void SetGenStdLib(bool genStdLib)
104     {
105         genStdLib_ = genStdLib;
106     }
107 
IsGenStdLib()108     bool IsGenStdLib()
109     {
110         return genStdLib_;
111     }
112 
GetScope()113     Scope *GetScope() const
114     {
115         return scope_;
116     }
117 
ResetAllScopes(GlobalScope * topScope,VariableScope * varScope,Scope * scope)118     void ResetAllScopes(GlobalScope *topScope, VariableScope *varScope, Scope *scope)
119     {
120         topScope_ = topScope;
121         varScope_ = varScope;
122         scope_ = scope;
123     }
124 
ResetTopScope(GlobalScope * topScope)125     void ResetTopScope(GlobalScope *topScope)
126     {
127         ASSERT(topScope_ == scope_);
128         topScope_ = topScope;
129         varScope_ = topScope_;
130         scope_ = topScope_;
131     }
132 
TopScope()133     GlobalScope *TopScope() const
134     {
135         return topScope_;
136     }
137 
VarScope()138     VariableScope *VarScope() const
139     {
140         return varScope_;
141     }
142 
IsETSBinder()143     bool IsETSBinder() const
144     {
145         return Extension() == ScriptExtension::ETS;
146     }
147 
AsETSBinder()148     ETSBinder *AsETSBinder()
149     {
150         ASSERT(Extension() == ScriptExtension::ETS);
151         return reinterpret_cast<ETSBinder *>(this);
152     }
153 
154     [[noreturn]] void ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const;
155     [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const;
156     [[noreturn]] void ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const;
157     [[noreturn]] void ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const;
158     [[noreturn]] void ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const;
159     [[noreturn]] void ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const;
160     [[noreturn]] void ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const;
161 
162     void PropagateDirectEval() const;
163 
164     template <typename T>
165     friend class LexicalScope;
166 
Allocator()167     inline ArenaAllocator *Allocator() const
168     {
169         return allocator_;
170     }
171 
Functions()172     const ArenaVector<FunctionScope *> &Functions() const
173     {
174         return functionScopes_;
175     }
176 
Functions()177     ArenaVector<FunctionScope *> &Functions()
178     {
179         return functionScopes_;
180     }
181 
Extension()182     virtual ScriptExtension Extension() const
183     {
184         return ScriptExtension::JS;
185     }
186 
BindingOptions()187     virtual ResolveBindingOptions BindingOptions() const
188     {
189         return ResolveBindingOptions::BINDINGS;
190     }
191 
192     LocalVariable *AddMandatoryParam(const std::string_view &name);
193 
194     static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
195     static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f";
196     static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt";
197     static constexpr std::string_view MANDATORY_PARAM_THIS = "=t";
198 
199     static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
200     static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
201 
202     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f";
203     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt";
204     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t";
205 
206     static constexpr std::string_view LEXICAL_CONTEXT_PARAM = "=eval";
207     static constexpr std::string_view MAIN = "main";
208     static constexpr uint32_t LEXICAL_CONTEXT_PARAM_REG = MANDATORY_PARAMS_NUMBER;
209     static constexpr std::string_view STAR_IMPORT = "*";
210 
211     void ResolveReferenceDoWhileHelper(ir::AstNode *childNode);
212     void ResolveReferenceWhileHelper(ir::AstNode *childNode);
213     void ResolveReference(ir::AstNode *childNode);
214 
215 protected:
216     template <size_t N>
217     using MandatoryParams = std::array<std::string_view, N>;
218 
219     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> FUNCTION_MANDATORY_PARAMS = {
220         MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS};
221 
222     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER + 1> EVAL_SCRIPT_MANDATORY_PARAMS = {
223         MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS, LEXICAL_CONTEXT_PARAM};
224 
225     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> ARROW_MANDATORY_PARAMS = {
226         MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
227 
228     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> CTOR_ARROW_MANDATORY_PARAMS = {
229         LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
230 
231     void LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj);
232     template <size_t N>
233     void AddMandatoryParams(const MandatoryParams<N> &params);
234     void AddMandatoryParams();
235     void LookupReference(const util::StringView &name);
236     void InstantiateArguments();
237     bool InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node);
238     void InstantiatePrivateContext(const ir::Identifier *ident) const;
239     void BuildVarDeclarator(ir::VariableDeclarator *varDecl);
240     void BuildVarDeclaratorId(ir::AstNode *childNode);
241     void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt);
242     void BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
243                           ir::Statement *body);
244     void BuildCatchClause(ir::CatchClause *catchClauseStmt);
245     void BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl);
246     void ResolveReferences(const ir::AstNode *parent);
247     void VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func);
248     void VisitScriptFunction(ir::ScriptFunction *func);
249     util::StringView BuildFunctionName(util::StringView name, uint32_t idx);
250 
251     void AddCompilableFunctionScope(varbinder::FunctionScope *funcScope);
252 
253     void InitializeClassBinding(ir::ClassDefinition *classDef);
254     void InitializeClassIdent(ir::ClassDefinition *classDef);
255 
256     virtual void LookupIdentReference(ir::Identifier *ident);
HandleCustomNodes(ir::AstNode * childNode)257     virtual void HandleCustomNodes(ir::AstNode *childNode)
258     {
259         ResolveReferences(childNode);
260     }
BuildSignatureDeclarationBaseParams(ir::AstNode * typeNode)261     virtual void BuildSignatureDeclarationBaseParams([[maybe_unused]] ir::AstNode *typeNode) {};
262     virtual void BuildClassDefinition(ir::ClassDefinition *classDef);
263     virtual void BuildClassProperty(const ir::ClassProperty *prop);
264     virtual bool BuildInternalName(ir::ScriptFunction *scriptFunc);
265     virtual void AddCompilableFunction(ir::ScriptFunction *func);
266 
267 private:
268     parser::Program *program_ {};
269     ArenaAllocator *allocator_ {};
270     public_lib::Context *context_ {};
271     GlobalScope *topScope_ {};
272     Scope *scope_ {};
273     VariableScope *varScope_ {};
274     ArenaVector<FunctionScope *> functionScopes_;
275     ResolveBindingOptions bindingOptions_ {};
276     bool genStdLib_ {false};
277 };
278 
279 template <typename T>
280 class LexicalScope {
281 public:
282     template <typename... Args>
LexicalScope(VarBinder * varbinder,Args &&...args)283     explicit LexicalScope(VarBinder *varbinder, Args &&...args)
284         : LexicalScope(
285               varbinder->Allocator()->New<T>(varbinder->Allocator(), varbinder->scope_, std::forward<Args>(args)...),
286               varbinder)
287     {
288     }
289 
GetScope()290     T *GetScope() const
291     {
292         return scope_;
293     }
294 
~LexicalScope()295     ~LexicalScope()
296     {
297         ASSERT(varbinder_);
298         varbinder_->scope_ = prevScope_;
299         varbinder_->varScope_ = prevVarScope_;
300     }
301 
302     [[nodiscard]] static LexicalScope<T> Enter(VarBinder *varbinder, T *scope, bool checkEval = true)
303     {
304         LexicalScope<T> lexScope(scope, varbinder);
305         if (!checkEval || varbinder->Extension() == ScriptExtension::TS) {
306             return lexScope;
307         }
308 
309         // NOLINTNEXTLINE(readability-braces-around-statements)
310         if constexpr (std::is_same_v<T, FunctionParamScope>) {
311             varbinder->varScope_ = scope->GetFunctionScope();
312             varbinder->varScope_->CheckDirectEval(varbinder->context_);
313             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
314         } else if constexpr (std::is_same_v<T, FunctionScope>) {
315             varbinder->varScope_ = scope;
316             varbinder->varScope_->CheckDirectEval(varbinder->context_);
317             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
318         } else if constexpr (std::is_same_v<T, LoopScope>) {
319             if (scope->IsLoopScope()) {
320                 varbinder->varScope_ = scope;
321                 varbinder->varScope_->CheckDirectEval(varbinder->context_);
322             }
323             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
324         } else if constexpr (std::is_same_v<T, LoopDeclarationScope>) {
325             if (scope->IsLoopDeclarationScope()) {
326                 varbinder->varScope_ = scope;
327                 varbinder->varScope_->CheckDirectEval(varbinder->context_);
328             }
329         }
330 
331         return lexScope;
332     }
333 
334     DEFAULT_MOVE_SEMANTIC(LexicalScope);
335 
336 private:
337     NO_COPY_SEMANTIC(LexicalScope);
338 
LexicalScope(T * scope,VarBinder * varbinder)339     explicit LexicalScope(T *scope, VarBinder *varbinder)
340         : varbinder_(varbinder), scope_(scope), prevScope_(varbinder->scope_), prevVarScope_(varbinder->varScope_)
341     {
342         varbinder_->scope_ = scope_;
343     }
344 
345     VarBinder *varbinder_ {};
346     T *scope_ {};
347     Scope *prevScope_ {};
348     VariableScope *prevVarScope_ {};
349 };
350 
351 template <size_t N>
AddMandatoryParams(const MandatoryParams<N> & params)352 void VarBinder::AddMandatoryParams(const MandatoryParams<N> &params)
353 {
354     ASSERT(scope_->IsFunctionVariableScope());
355 
356     auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope_->AsFunctionVariableScope()->ParamScope());
357 
358     for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
359         AddMandatoryParam(*iter);
360     }
361 }
362 
363 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,Args &&...args)364 T *VarBinder::AddTsDecl(const lexer::SourcePosition &pos, Args &&...args)
365 {
366     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
367 
368     if (scope_->AddTsDecl(Allocator(), decl, Extension()) != nullptr) {
369         return decl;
370     }
371 
372     ThrowRedeclaration(pos, decl->Name());
373 }
374 
375 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,Args &&...args)376 T *VarBinder::AddDecl(const lexer::SourcePosition &pos, Args &&...args)
377 {
378     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
379 
380     if (scope_->AddDecl(Allocator(), decl, Extension()) != nullptr) {
381         return decl;
382     }
383 
384     ThrowRedeclaration(pos, decl->Name());
385 }
386 
387 template <typename T, typename... Args>
NewVarDecl(const lexer::SourcePosition & pos,Args &&...args)388 std::tuple<T *, varbinder::Variable *> VarBinder::NewVarDecl(const lexer::SourcePosition &pos, Args &&...args)
389 {
390     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
391     varbinder::Variable *var = scope_->AddDecl(Allocator(), decl, Extension());
392 
393     if (var != nullptr) {
394         return {decl, var};
395     }
396 
397     ThrowRedeclaration(pos, decl->Name());
398 }
399 }  // namespace ark::es2panda::varbinder
400 
401 #endif
402