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> ¶ms);
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> ¶ms)
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