• 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 
ResetTopScope(GlobalScope * topScope)118     void ResetTopScope(GlobalScope *topScope)
119     {
120         ASSERT(topScope_ == scope_);
121         topScope_ = topScope;
122         varScope_ = topScope_;
123         scope_ = topScope_;
124     }
125 
TopScope()126     GlobalScope *TopScope() const
127     {
128         return topScope_;
129     }
130 
VarScope()131     VariableScope *VarScope() const
132     {
133         return varScope_;
134     }
135 
IsETSBinder()136     bool IsETSBinder() const
137     {
138         return Extension() == ScriptExtension::ETS;
139     }
140 
AsETSBinder()141     ETSBinder *AsETSBinder()
142     {
143         ASSERT(Extension() == ScriptExtension::ETS);
144         return reinterpret_cast<ETSBinder *>(this);
145     }
146 
147     [[noreturn]] void ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const;
148     [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const;
149     [[noreturn]] void ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const;
150     [[noreturn]] void ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const;
151     [[noreturn]] void ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const;
152     [[noreturn]] void ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const;
153     [[noreturn]] void ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const;
154 
155     void PropagateDirectEval() const;
156 
157     template <typename T>
158     friend class LexicalScope;
159 
Allocator()160     inline ArenaAllocator *Allocator() const
161     {
162         return allocator_;
163     }
164 
Functions()165     const ArenaVector<FunctionScope *> &Functions() const
166     {
167         return functionScopes_;
168     }
169 
Functions()170     ArenaVector<FunctionScope *> &Functions()
171     {
172         return functionScopes_;
173     }
174 
Extension()175     virtual ScriptExtension Extension() const
176     {
177         return ScriptExtension::JS;
178     }
179 
BindingOptions()180     virtual ResolveBindingOptions BindingOptions() const
181     {
182         return ResolveBindingOptions::BINDINGS;
183     }
184 
185     LocalVariable *AddMandatoryParam(const std::string_view &name);
186 
187     static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
188     static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f";
189     static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt";
190     static constexpr std::string_view MANDATORY_PARAM_THIS = "=t";
191 
192     static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
193     static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
194 
195     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f";
196     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt";
197     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t";
198 
199     static constexpr std::string_view LEXICAL_CONTEXT_PARAM = "=eval";
200     static constexpr std::string_view MAIN = "main";
201     static constexpr uint32_t LEXICAL_CONTEXT_PARAM_REG = MANDATORY_PARAMS_NUMBER;
202     static constexpr std::string_view STAR_IMPORT = "*";
203 
204     void ResolveReference(ir::AstNode *childNode);
205 
206 protected:
207     template <size_t N>
208     using MandatoryParams = std::array<std::string_view, N>;
209 
210     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> FUNCTION_MANDATORY_PARAMS = {
211         MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS};
212 
213     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER + 1> EVAL_SCRIPT_MANDATORY_PARAMS = {
214         MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS, LEXICAL_CONTEXT_PARAM};
215 
216     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> ARROW_MANDATORY_PARAMS = {
217         MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
218 
219     static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> CTOR_ARROW_MANDATORY_PARAMS = {
220         LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
221 
222     void LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj);
223     template <size_t N>
224     void AddMandatoryParams(const MandatoryParams<N> &params);
225     void AddMandatoryParams();
226     void LookupReference(const util::StringView &name);
227     void InstantiateArguments();
228     bool InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node);
229     void InstantiatePrivateContext(const ir::Identifier *ident) const;
230     void BuildVarDeclarator(ir::VariableDeclarator *varDecl);
231     void BuildVarDeclaratorId(ir::AstNode *childNode);
232     void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt);
233     void BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
234                           ir::Statement *body);
235     void BuildCatchClause(ir::CatchClause *catchClauseStmt);
236     void BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl);
237     void ResolveReferences(const ir::AstNode *parent);
238     void VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func);
239     void VisitScriptFunction(ir::ScriptFunction *func);
240     util::StringView BuildFunctionName(util::StringView name, uint32_t idx);
241 
242     void AddCompilableFunctionScope(varbinder::FunctionScope *funcScope);
243 
244     void InitializeClassBinding(ir::ClassDefinition *classDef);
245     void InitializeClassIdent(ir::ClassDefinition *classDef);
246 
247     virtual void LookupIdentReference(ir::Identifier *ident);
HandleCustomNodes(ir::AstNode * childNode)248     virtual void HandleCustomNodes(ir::AstNode *childNode)
249     {
250         ResolveReferences(childNode);
251     }
BuildSignatureDeclarationBaseParams(ir::AstNode * typeNode)252     virtual void BuildSignatureDeclarationBaseParams([[maybe_unused]] ir::AstNode *typeNode) {};
253     virtual void BuildClassDefinition(ir::ClassDefinition *classDef);
254     virtual void BuildClassProperty(const ir::ClassProperty *prop);
255     virtual bool BuildInternalName(ir::ScriptFunction *scriptFunc);
256     virtual void AddCompilableFunction(ir::ScriptFunction *func);
257 
258 private:
259     parser::Program *program_ {};
260     ArenaAllocator *allocator_ {};
261     public_lib::Context *context_ {};
262     GlobalScope *topScope_ {};
263     Scope *scope_ {};
264     VariableScope *varScope_ {};
265     ArenaVector<FunctionScope *> functionScopes_;
266     ResolveBindingOptions bindingOptions_ {};
267     bool genStdLib_ {false};
268 };
269 
270 template <typename T>
271 class LexicalScope {
272 public:
273     template <typename... Args>
LexicalScope(VarBinder * varbinder,Args &&...args)274     explicit LexicalScope(VarBinder *varbinder, Args &&...args)
275         : LexicalScope(
276               varbinder->Allocator()->New<T>(varbinder->Allocator(), varbinder->scope_, std::forward<Args>(args)...),
277               varbinder)
278     {
279     }
280 
GetScope()281     T *GetScope() const
282     {
283         return scope_;
284     }
285 
~LexicalScope()286     ~LexicalScope()
287     {
288         ASSERT(varbinder_);
289         varbinder_->scope_ = prevScope_;
290         varbinder_->varScope_ = prevVarScope_;
291     }
292 
293     [[nodiscard]] static LexicalScope<T> Enter(VarBinder *varbinder, T *scope, bool checkEval = true)
294     {
295         LexicalScope<T> lexScope(scope, varbinder);
296         if (!checkEval || varbinder->Extension() == ScriptExtension::TS) {
297             return lexScope;
298         }
299 
300         // NOLINTNEXTLINE(readability-braces-around-statements)
301         if constexpr (std::is_same_v<T, FunctionParamScope>) {
302             varbinder->varScope_ = scope->GetFunctionScope();
303             varbinder->varScope_->CheckDirectEval(varbinder->context_);
304             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
305         } else if constexpr (std::is_same_v<T, FunctionScope>) {
306             varbinder->varScope_ = scope;
307             varbinder->varScope_->CheckDirectEval(varbinder->context_);
308             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
309         } else if constexpr (std::is_same_v<T, LoopScope>) {
310             if (scope->IsLoopScope()) {
311                 varbinder->varScope_ = scope;
312                 varbinder->varScope_->CheckDirectEval(varbinder->context_);
313             }
314             // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
315         } else if constexpr (std::is_same_v<T, LoopDeclarationScope>) {
316             if (scope->IsLoopDeclarationScope()) {
317                 varbinder->varScope_ = scope;
318                 varbinder->varScope_->CheckDirectEval(varbinder->context_);
319             }
320         }
321 
322         return lexScope;
323     }
324 
325     DEFAULT_MOVE_SEMANTIC(LexicalScope);
326 
327 private:
328     NO_COPY_SEMANTIC(LexicalScope);
329 
LexicalScope(T * scope,VarBinder * varbinder)330     explicit LexicalScope(T *scope, VarBinder *varbinder)
331         : varbinder_(varbinder), scope_(scope), prevScope_(varbinder->scope_), prevVarScope_(varbinder->varScope_)
332     {
333         varbinder_->scope_ = scope_;
334     }
335 
336     VarBinder *varbinder_ {};
337     T *scope_ {};
338     Scope *prevScope_ {};
339     VariableScope *prevVarScope_ {};
340 };
341 
342 template <size_t N>
AddMandatoryParams(const MandatoryParams<N> & params)343 void VarBinder::AddMandatoryParams(const MandatoryParams<N> &params)
344 {
345     ASSERT(scope_->IsFunctionVariableScope());
346 
347     auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope_->AsFunctionVariableScope()->ParamScope());
348 
349     for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
350         AddMandatoryParam(*iter);
351     }
352 }
353 
354 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,Args &&...args)355 T *VarBinder::AddTsDecl(const lexer::SourcePosition &pos, Args &&...args)
356 {
357     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
358 
359     if (scope_->AddTsDecl(Allocator(), decl, Extension()) != nullptr) {
360         return decl;
361     }
362 
363     ThrowRedeclaration(pos, decl->Name());
364 }
365 
366 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,Args &&...args)367 T *VarBinder::AddDecl(const lexer::SourcePosition &pos, Args &&...args)
368 {
369     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
370 
371     if (scope_->AddDecl(Allocator(), decl, Extension()) != nullptr) {
372         return decl;
373     }
374 
375     ThrowRedeclaration(pos, decl->Name());
376 }
377 
378 template <typename T, typename... Args>
NewVarDecl(const lexer::SourcePosition & pos,Args &&...args)379 std::tuple<T *, varbinder::Variable *> VarBinder::NewVarDecl(const lexer::SourcePosition &pos, Args &&...args)
380 {
381     T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
382     varbinder::Variable *var = scope_->AddDecl(Allocator(), decl, Extension());
383 
384     if (var != nullptr) {
385         return {decl, var};
386     }
387 
388     ThrowRedeclaration(pos, decl->Name());
389 }
390 }  // namespace ark::es2panda::varbinder
391 
392 #endif
393