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_BINDER_BINDER_H 17#define ES2PANDA_BINDER_BINDER_H 18 19#include <binder/scope.h> 20#include <binder/variableFlags.h> 21#include <lexer/token/sourceLocation.h> 22#include <macros.h> 23#include <parser/program/program.h> 24 25namespace panda::es2panda::ir { 26class AstNode; 27class BlockStatement; 28class CatchClause; 29class ClassDefinition; 30class Expression; 31class ExportNamedDeclaration; 32class ForUpdateStatement; 33class Identifier; 34class PrivateIdentifier; 35class ScriptFunction; 36class Statement; 37class VariableDeclarator; 38class TSFunctionType; 39} // namespace panda::es2panda::ir 40 41namespace panda::es2panda::binder { 42class Scope; 43class VariableScope; 44 45class Binder { 46public: 47 explicit Binder(parser::Program *program, ScriptExtension extension) 48 : program_(program), 49 functionScopes_(Allocator()->Adapter()), 50 functionNames_(Allocator()->Adapter()), 51 anonymousFunctionNames_(Allocator()->Adapter()), 52 functionHashNames_(Allocator()->Adapter()), 53 variableNames_(Allocator()->Adapter()), 54 specialFuncNameIndexMap_(Allocator()->Adapter()), 55 extension_(extension) 56 { 57 if (extension_ == ScriptExtension::TS) { 58 bindingOptions_ = ResolveBindingOptions::ALL; 59 return; 60 } 61 62 bindingOptions_ = ResolveBindingOptions::BINDINGS; 63 } 64 65 NO_COPY_SEMANTIC(Binder); 66 DEFAULT_MOVE_SEMANTIC(Binder); 67 ~Binder() = default; 68 69 void InitTopScope(); 70 void IdentifierAnalysis(ResolveBindingFlags flags = ResolveBindingFlags::ALL); 71 72 template <typename T, typename... Args> 73 T *AddDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args); 74 75 template <typename T, typename... Args> 76 T *AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args); 77 78 template <typename T, typename... Args> 79 T *AddTsDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args); 80 81 template <typename T, typename... Args> 82 T *AddTsDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args); 83 84 ParameterDecl *AddParamDecl(const ir::AstNode *param); 85 86 Scope *GetScope() const 87 { 88 return scope_; 89 } 90 91 FunctionScope *TopScope() const 92 { 93 return topScope_; 94 } 95 96 [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name); 97 [[noreturn]] void ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name); 98 [[noreturn]] void ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name); 99 [[noreturn]] void ThrowInvalidAnnotationDeclaration(const lexer::SourcePosition &pos, const util::StringView &name); 100 101 void CheckMandatoryArguments(const ir::Identifier *ident); 102 103 template <typename T> 104 friend class LexicalScope; 105 106 inline ArenaAllocator *Allocator() const 107 { 108 return program_->Allocator(); 109 } 110 111 const ArenaVector<FunctionScope *> &Functions() const 112 { 113 return functionScopes_; 114 } 115 116 ArenaVector<FunctionScope *> Functions() 117 { 118 return functionScopes_; 119 } 120 121 const parser::Program *Program() const 122 { 123 return program_; 124 } 125 126 void SetProgram(parser::Program *program) 127 { 128 program_ = program; 129 } 130 131 ArenaUnorderedMap<util::StringView, int32_t> &GetScopeNames() 132 { 133 return topScope_->GetScopeNames(); 134 } 135 136 const ArenaUnorderedMap<const ir::ScriptFunction *, util::StringView> &AnonymousFunctionNames() const 137 { 138 return anonymousFunctionNames_; 139 } 140 141 const ArenaUnorderedMap<std::string, std::string> &SpecialFuncNameIndexMap() const 142 { 143 return specialFuncNameIndexMap_; 144 } 145 146 void AddDeclarationName(const util::StringView &name, DeclType type = DeclType::NONE); 147 148 bool HasVariableName(const util::StringView &name) const; 149 150 std::vector<Variable *> FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope, 151 ScopeFindResult &res); 152 153 static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments"; 154 static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj"; 155 static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget"; 156 static constexpr std::string_view MANDATORY_PARAM_THIS = "this"; 157 158 static constexpr std::string_view CJS_MANDATORY_PARAM_EXPORTS = "exports"; 159 static constexpr std::string_view CJS_MANDATORY_PARAM_REQUIRE = "require"; 160 static constexpr std::string_view CJS_MANDATORY_PARAM_MODULE = "module"; 161 static constexpr std::string_view CJS_MANDATORY_PARAM_FILENAME = "__filename"; 162 static constexpr std::string_view CJS_MANDATORY_PARAM_DIRNAME = "__dirname"; 163 164 static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0; 165 static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3; 166 static constexpr uint32_t CJS_MANDATORY_PARAMS_NUMBER = 8; 167 168 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "0funcObj"; 169 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "0newTarget"; 170 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "0this"; 171 172 static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0"; 173 static constexpr std::string_view ANONYMOUS_FUNC_NAME = ""; 174 static constexpr std::string_view ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER = "#"; 175 176private: 177 using MandatoryParams = std::array<std::string_view, MANDATORY_PARAMS_NUMBER>; 178 using CommonjsMandatoryParams = std::array<std::string_view, CJS_MANDATORY_PARAMS_NUMBER>; 179 180 static constexpr MandatoryParams FUNCTION_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, 181 MANDATORY_PARAM_THIS}; 182 183 static constexpr MandatoryParams ARROW_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, 184 LEXICAL_MANDATORY_PARAM_THIS}; 185 186 static constexpr MandatoryParams CTOR_ARROW_MANDATORY_PARAMS = { 187 LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS}; 188 189 static constexpr CommonjsMandatoryParams CJS_MAINFUNC_MANDATORY_PARAMS = { 190 MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS, 191 CJS_MANDATORY_PARAM_EXPORTS, CJS_MANDATORY_PARAM_REQUIRE, CJS_MANDATORY_PARAM_MODULE, 192 CJS_MANDATORY_PARAM_FILENAME, CJS_MANDATORY_PARAM_DIRNAME}; 193 194 void AddMandatoryParam(const std::string_view &name); 195 196 template<typename T> 197 void AddMandatoryParams(const T ¶ms) 198 { 199 for (auto iter = params.rbegin(); iter != params.rend(); iter++) { 200 AddMandatoryParam(*iter); 201 } 202 } 203 204 void AddMandatoryParams(); 205 void AssignIndexToModuleVariable(); 206 void BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr); 207 void LegacyBuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr); 208 void BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc); 209 void BuildClassDefinition(ir::ClassDefinition *classDef); 210 void LookupReference(const util::StringView &name); 211 void InstantiateArguments(); 212 void BuildVarDeclarator(ir::VariableDeclarator *varDecl); 213 void BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode); 214 void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt); 215 void BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left, 216 ir::Expression *right, ir::Statement *body); 217 void BuildCatchClause(ir::CatchClause *catchClauseStmt); 218 void LookupIdentReference(ir::Identifier *ident); 219 void ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode); 220 void ResolveReferences(const ir::AstNode *parent); 221 void ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl); 222 void StoreAndCheckSpecialFunctionName(std::string &internalNameStr, std::string recordName); 223 void ReplaceConstReferenceWithInitialization(const ir::Identifier *ident, const Decl *decl); 224 void CheckPrivateDeclaration(const ir::PrivateIdentifier *privateIdent); 225 226 // TypeScript specific functions 227 void BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode); 228 void BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode *parent, ir::AstNode *typeNode); 229 230 parser::Program *program_ {}; 231 FunctionScope *topScope_ {}; 232 Scope *scope_ {}; 233 ArenaVector<FunctionScope *> functionScopes_; 234 ResolveBindingOptions bindingOptions_; 235 ArenaSet<util::StringView> functionNames_; 236 ArenaUnorderedMap<const ir::ScriptFunction *, util::StringView> anonymousFunctionNames_; 237 ArenaUnorderedMap<std::string, size_t> functionHashNames_; 238 ArenaSet<util::StringView> variableNames_; 239 uint32_t globalIndexForSpecialFunc_ {0}; 240 ArenaUnorderedMap<std::string, std::string> specialFuncNameIndexMap_; 241 ResolveBindingFlags bindingFlags_ {ResolveBindingFlags::ALL}; 242 ScriptExtension extension_; 243 bool inSendableClass_ {false}; 244 bool inSendableFunction_ {false}; 245}; 246 247template <typename T> 248class LexicalScope { 249public: 250 template <typename... Args> 251 explicit LexicalScope(Binder *binder, Args &&... args) 252 : LexicalScope(binder->Allocator()->New<T>(binder->Allocator(), binder->scope_, std::forward<Args>(args)...), 253 binder) 254 { 255 } 256 257 T *GetScope() const 258 { 259 return scope_; 260 } 261 262 ~LexicalScope() 263 { 264 ASSERT(binder_); 265 binder_->scope_ = prevScope_; 266 } 267 268 [[nodiscard]] static LexicalScope<T> Enter(Binder *binder, T *scope) 269 { 270 LexicalScope<T> lexScope(scope, binder); 271 return lexScope; 272 } 273 274 DEFAULT_MOVE_SEMANTIC(LexicalScope); 275 276private: 277 NO_COPY_SEMANTIC(LexicalScope); 278 279 explicit LexicalScope(T *scope, Binder *binder) : binder_(binder), scope_(scope), prevScope_(binder->scope_) 280 { 281 binder_->scope_ = scope_; 282 } 283 284 Binder *binder_ {}; 285 T *scope_ {}; 286 Scope *prevScope_ {}; 287}; 288 289template <typename T, typename... Args> 290T *Binder::AddTsDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args) 291{ 292 T *decl = Allocator()->New<T>(std::forward<Args>(args)...); 293 if (decl == nullptr) { 294 throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding ts decl during binder"); 295 } 296 decl->SetDeclare(isDeclare); 297 298 if (scope_->AddTsDecl(Allocator(), decl, program_->Extension())) { 299 AddDeclarationName(decl->Name()); 300 return decl; 301 } 302 303 ThrowRedeclaration(pos, decl->Name()); 304} 305 306template <typename T, typename... Args> 307T *Binder::AddTsDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args) 308{ 309 T *decl = Allocator()->New<T>(std::forward<Args>(args)...); 310 if (decl == nullptr) { 311 throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding ts decl during binder"); 312 } 313 decl->AddFlag(flag); 314 decl->SetDeclare(isDeclare); 315 316 if (scope_->AddTsDecl(Allocator(), decl, program_->Extension())) { 317 AddDeclarationName(decl->Name()); 318 return decl; 319 } 320 321 ThrowRedeclaration(pos, decl->Name()); 322} 323 324template <typename T, typename... Args> 325T *Binder::AddDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args) 326{ 327 T *decl = Allocator()->New<T>(std::forward<Args>(args)...); 328 if (decl == nullptr) { 329 throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding decl during binder"); 330 } 331 decl->SetDeclare(isDeclare); 332 333 if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { 334 AddDeclarationName(decl->Name(), decl->Type()); 335 return decl; 336 } 337 338 ThrowRedeclaration(pos, decl->Name()); 339} 340 341template <typename T, typename... Args> 342T *Binder::AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args) 343{ 344 T *decl = Allocator()->New<T>(std::forward<Args>(args)...); 345 if (decl == nullptr) { 346 throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding decl during binder"); 347 } 348 decl->AddFlag(flag); 349 decl->SetDeclare(isDeclare); 350 351 if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { 352 AddDeclarationName(decl->Name(), decl->Type()); 353 return decl; 354 } 355 356 ThrowRedeclaration(pos, decl->Name()); 357} 358 359class ClassTdz { 360public: 361 explicit ClassTdz(const ir::AstNode *parent, const ir::AstNode *childNode, Scope *scope); 362 363 ~ClassTdz() 364 { 365 if (variable_) { 366 variable_->AddFlag(VariableFlags::INITIALIZED); 367 } 368 } 369 370private: 371 Variable *variable_ {}; 372}; 373 374} // namespace panda::es2panda::binder 375 376#endif 377