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