1 /*
2 * Copyright (c) 2023-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 #include "util/errorHandler.h"
17 #include "scopesInitPhase.h"
18
19 namespace ark::es2panda::compiler {
20
21 template <typename T>
LexicalScopeCreateOrEnter(varbinder::VarBinder * varBinder,ir::AstNode * ast)22 varbinder::LexicalScope<T> LexicalScopeCreateOrEnter(varbinder::VarBinder *varBinder, ir::AstNode *ast)
23 {
24 if (ast != nullptr && ast->Scope() != nullptr) {
25 return varbinder::LexicalScope<T>::Enter(varBinder, reinterpret_cast<T *>(ast->Scope()));
26 }
27 return varbinder::LexicalScope<T>(varBinder);
28 }
29
30 template <typename T, typename... Args>
AddOrGetDecl(varbinder::VarBinder * varBinder,util::StringView name,ir::AstNode * ast,const lexer::SourcePosition & pos,Args &&...args)31 T *AddOrGetDecl(varbinder::VarBinder *varBinder, util::StringView name, ir::AstNode *ast,
32 const lexer::SourcePosition &pos, Args &&...args)
33 {
34 if (auto *var = varBinder->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
35 var != nullptr && var->Declaration() != nullptr && var->Declaration()->Node() == ast) {
36 return reinterpret_cast<T *>(var->Declaration());
37 }
38 return varBinder->AddDecl<T>(pos, args...);
39 }
40
Perform(PhaseContext * ctx,parser::Program * program)41 bool ScopesInitPhase::Perform(PhaseContext *ctx, parser::Program *program)
42 {
43 Prepare(ctx, program);
44 program->VarBinder()->InitTopScope();
45 HandleBlockStmt(program->Ast(), GetScope());
46 Finalize();
47 return true;
48 }
49
VisitScriptFunction(ir::ScriptFunction * scriptFunction)50 void ScopesInitPhase::VisitScriptFunction(ir::ScriptFunction *scriptFunction)
51 {
52 HandleFunction(scriptFunction);
53 }
54
VisitBlockStatement(ir::BlockStatement * blockStmt)55 void ScopesInitPhase::VisitBlockStatement(ir::BlockStatement *blockStmt)
56 {
57 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), blockStmt);
58 HandleBlockStmt(blockStmt, GetScope());
59 }
60
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)61 void ScopesInitPhase::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
62 {
63 ImportDeclarationContext importCtx(VarBinder());
64 Iterate(importDeclaration);
65 importCtx.BindImportDecl(importDeclaration);
66 }
67
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)68 void ScopesInitPhase::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
69 {
70 Iterate(staticBlock);
71 }
72
VisitMethodDefinition(ir::MethodDefinition * methodDefinition)73 void ScopesInitPhase::VisitMethodDefinition(ir::MethodDefinition *methodDefinition)
74 {
75 Iterate(methodDefinition);
76 }
77
HandleFunctionSig(ir::TSTypeParameterDeclaration * typeParams,const ir::FunctionSignature::FunctionParams & params,ir::TypeNode * returnType)78 varbinder::FunctionParamScope *ScopesInitPhase::HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams,
79 const ir::FunctionSignature::FunctionParams ¶ms,
80 ir::TypeNode *returnType)
81 {
82 auto typeParamsCtx = varbinder::LexicalScope<varbinder::LocalScope>(VarBinder());
83 CallNode(typeParams);
84
85 auto lexicalScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder());
86 CallFuncParams(params);
87 CallNode(returnType);
88
89 return lexicalScope.GetScope();
90 }
91
HandleFunction(ir::ScriptFunction * function)92 void ScopesInitPhase::HandleFunction(ir::ScriptFunction *function)
93 {
94 CallNode(function->Id());
95 // NOTE(gogabr): this will skip type/value parameters when they are added to an existing function sig
96 auto funcParamScope = (function->Scope() == nullptr) ? HandleFunctionSig(function->TypeParams(), function->Params(),
97 function->ReturnTypeAnnotation())
98 : function->Scope()->ParamScope();
99 auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false);
100
101 auto functionCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), function);
102 auto *functionScope = functionCtx.GetScope();
103 BindFunctionScopes(functionScope, funcParamScope);
104
105 if (function->Body() != nullptr && function->Body()->IsBlockStatement()) {
106 HandleBlockStmt(function->Body()->AsBlockStatement(), functionScope);
107 } else {
108 Iterate(function->Body());
109 }
110 BindScopeNode(functionScope, function);
111 funcParamScope->BindNode(function);
112 }
113
HandleBlockStmt(ir::BlockStatement * block,varbinder::Scope * scope)114 void ScopesInitPhase::HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope)
115 {
116 if (block->Scope() == nullptr) {
117 BindScopeNode(scope, block);
118 }
119 Iterate(block);
120 }
121
VisitClassDefinition(ir::ClassDefinition * classDef)122 void ScopesInitPhase::VisitClassDefinition(ir::ClassDefinition *classDef)
123 {
124 auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
125 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
126 classDef->PrivateId());
127 BindClassName(classDef);
128
129 auto *classScope = classCtx.GetScope();
130 BindScopeNode(classScope, classDef);
131 Iterate(classDef);
132 }
133
VisitForUpdateStatement(ir::ForUpdateStatement * forUpdateStmt)134 void ScopesInitPhase::VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt)
135 {
136 auto declCtx = (forUpdateStmt->Scope() == nullptr)
137 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
138 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
139 VarBinder(), forUpdateStmt->Scope()->DeclScope());
140 CallNode(forUpdateStmt->Init());
141
142 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forUpdateStmt);
143 AttachLabelToScope(forUpdateStmt);
144 CallNode(forUpdateStmt->Test());
145 CallNode(forUpdateStmt->Update());
146 CallNode(forUpdateStmt->Body());
147 lexicalScope.GetScope()->BindDecls(declCtx.GetScope());
148 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forUpdateStmt);
149 }
150
VisitForInStatement(ir::ForInStatement * forInStmt)151 void ScopesInitPhase::VisitForInStatement(ir::ForInStatement *forInStmt)
152 {
153 auto declCtx = (forInStmt->Scope() == nullptr)
154 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
155 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
156 VarBinder(), forInStmt->Scope()->DeclScope());
157 CallNode(forInStmt->Left());
158
159 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forInStmt);
160 CallNode(forInStmt->Right());
161 CallNode(forInStmt->Body());
162 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forInStmt);
163 }
VisitForOfStatement(ir::ForOfStatement * forOfStmt)164 void ScopesInitPhase::VisitForOfStatement(ir::ForOfStatement *forOfStmt)
165 {
166 auto declCtx = (forOfStmt->Scope() == nullptr)
167 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
168 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
169 VarBinder(), forOfStmt->Scope()->DeclScope());
170 CallNode(forOfStmt->Left());
171
172 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forOfStmt);
173 AttachLabelToScope(forOfStmt);
174 CallNode(forOfStmt->Right());
175 CallNode(forOfStmt->Body());
176 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forOfStmt);
177 }
178
VisitCatchClause(ir::CatchClause * catchClause)179 void ScopesInitPhase::VisitCatchClause(ir::CatchClause *catchClause)
180 {
181 auto catchParamCtx = (catchClause->Scope() == nullptr)
182 ? varbinder::LexicalScope<varbinder::CatchParamScope>(VarBinder())
183 : varbinder::LexicalScope<varbinder::CatchParamScope>::Enter(
184 VarBinder(), catchClause->Scope()->ParamScope());
185 auto *catchParamScope = catchParamCtx.GetScope();
186 auto *param = catchClause->Param();
187
188 CallNode(param);
189
190 if (param != nullptr) {
191 auto [param_decl, var] = VarBinder()->AddParamDecl(param);
192 (void)param_decl;
193 if (param->IsIdentifier()) {
194 var->SetScope(catchParamScope);
195 param->AsIdentifier()->SetVariable(var);
196 }
197 }
198 catchParamScope->BindNode(param);
199
200 auto catchCtx = LexicalScopeCreateOrEnter<varbinder::CatchScope>(VarBinder(), catchClause);
201 auto *catchScope = catchCtx.GetScope();
202
203 catchScope->AssignParamScope(catchParamScope);
204 auto body = catchClause->Body();
205 HandleBlockStmt(body, catchScope);
206
207 BindScopeNode(catchScope, catchClause);
208 }
209
VisitVariableDeclarator(ir::VariableDeclarator * varDecl)210 void ScopesInitPhase::VisitVariableDeclarator(ir::VariableDeclarator *varDecl)
211 {
212 auto init = varDecl->Id();
213 std::vector<ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
214 for (auto *binding : bindings) {
215 auto [decl, var] = AddOrGetVarDecl(varDecl->Flag(), varDecl->Start(), binding);
216 BindVarDecl(binding, init, decl, var);
217 }
218 Iterate(varDecl);
219 }
220
VisitSwitchStatement(ir::SwitchStatement * switchStmt)221 void ScopesInitPhase::VisitSwitchStatement(ir::SwitchStatement *switchStmt)
222 {
223 CallNode(switchStmt->Discriminant());
224 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), switchStmt);
225 AttachLabelToScope(switchStmt);
226 BindScopeNode(localCtx.GetScope(), switchStmt);
227 CallNode(switchStmt->Cases());
228 }
229
VisitWhileStatement(ir::WhileStatement * whileStmt)230 void ScopesInitPhase::VisitWhileStatement(ir::WhileStatement *whileStmt)
231 {
232 CallNode(whileStmt->Test());
233 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), whileStmt);
234 AttachLabelToScope(whileStmt);
235 BindScopeNode(lexicalScope.GetScope(), whileStmt);
236 CallNode(whileStmt->Body());
237 }
238
VisitETSStructDeclaration(ir::ETSStructDeclaration * structDecl)239 void ScopesInitPhase::VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl)
240 {
241 Iterate(structDecl);
242 BindClassDefinition(structDecl->Definition());
243 }
244
VisitClassDeclaration(ir::ClassDeclaration * classDecl)245 void ScopesInitPhase::VisitClassDeclaration(ir::ClassDeclaration *classDecl)
246 {
247 Iterate(classDecl);
248 BindClassDefinition(classDecl->Definition());
249 }
250
VisitDoWhileStatement(ir::DoWhileStatement * doWhileStmt)251 void ScopesInitPhase::VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt)
252 {
253 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), doWhileStmt);
254 AttachLabelToScope(doWhileStmt);
255 BindScopeNode(lexicalScope.GetScope(), doWhileStmt);
256 Iterate(doWhileStmt);
257 }
258
VisitFunctionDeclaration(ir::FunctionDeclaration * funcDecl)259 void ScopesInitPhase::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl)
260 {
261 const auto func = funcDecl->Function();
262 if (!funcDecl->IsAnonymous()) {
263 CreateFuncDecl(func);
264 }
265 Iterate(funcDecl);
266 }
267
VisitExportAllDeclaration(ir::ExportAllDeclaration * exportAllDecl)268 void ScopesInitPhase::VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl)
269 {
270 Iterate(exportAllDecl);
271 const auto name = exportAllDecl->Exported() != nullptr ? exportAllDecl->Exported()->Name() : "*";
272 auto *decl =
273 AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), name, exportAllDecl, exportAllDecl->Start(), name, "*");
274 VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportAllDecl, decl);
275 }
276
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)277 void ScopesInitPhase::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
278 {
279 Iterate(importSpec);
280 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(), "*",
281 importSpec->Local()->Name(), importSpec);
282 }
283
VisitImportSpecifier(ir::ImportSpecifier * importSpec)284 void ScopesInitPhase::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
285 {
286 Iterate(importSpec);
287 const auto *imported = importSpec->Imported();
288 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
289 imported->Name(), importSpec->Local()->Name(), importSpec);
290 }
291
VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier * importSpec)292 void ScopesInitPhase::VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec)
293 {
294 Iterate(importSpec);
295 const auto *local = importSpec->Local();
296 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), local->Name(), importSpec, local->Start(), "default",
297 local->Name(), importSpec);
298 }
299
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)300 void ScopesInitPhase::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
301 {
302 ExportDeclarationContext exportDeclCtx(VarBinder());
303 Iterate(exportDecl);
304 exportDeclCtx.BindExportDecl(exportDecl);
305 }
306
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)307 void ScopesInitPhase::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
308 {
309 Iterate(arrowExpr);
310 }
311
VisitDirectEvalExpression(ir::DirectEvalExpression * directCallExpr)312 void ScopesInitPhase::VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr)
313 {
314 VarBinder()->PropagateDirectEval();
315 Iterate(directCallExpr);
316 }
317
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)318 void ScopesInitPhase::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
319 {
320 if (exportDecl->Decl() != nullptr) {
321 ExportDeclarationContext exportDeclCtx(VarBinder());
322 Iterate(exportDecl);
323 exportDeclCtx.BindExportDecl(exportDecl);
324 } else {
325 varbinder::ModuleScope::ExportDeclList exportDecls(program_->Allocator()->Adapter());
326
327 for (auto *spec : exportDecl->Specifiers()) {
328 auto *decl =
329 AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), spec->Local()->Name(), spec, exportDecl->Start(),
330 spec->Exported()->Name(), spec->Local()->Name(), spec);
331 exportDecls.push_back(decl);
332 }
333 VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportDecl, std::move(exportDecls));
334 }
335 }
336
VisitTSFunctionType(ir::TSFunctionType * funcType)337 void ScopesInitPhase::VisitTSFunctionType(ir::TSFunctionType *funcType)
338 {
339 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::FunctionParamScope>(VarBinder(), funcType);
340 auto *funcParamScope = lexicalScope.GetScope();
341 BindScopeNode(funcParamScope, funcType);
342 Iterate(funcType);
343 }
344
SetProgram(parser::Program * program)345 void ScopesInitPhase::SetProgram(parser::Program *program) noexcept
346 {
347 program_ = program;
348 }
349
CallFuncParams(const ArenaVector<ir::Expression * > & params)350 void ScopesInitPhase::CallFuncParams(const ArenaVector<ir::Expression *> ¶ms)
351 {
352 // NOTE: extract params to separate class
353 for (auto *param : params) {
354 if (!param->IsETSParameterExpression()) {
355 VarBinder()->AddParamDecl(param);
356 }
357 }
358 CallNode(params);
359 }
360
IterateNoTParams(ir::ClassDefinition * classDef)361 void ScopesInitPhase::IterateNoTParams(ir::ClassDefinition *classDef)
362 {
363 CallNode(classDef->Super());
364 CallNode(classDef->SuperTypeParams());
365 CallNode(classDef->Implements());
366 CallNode(classDef->Ctor());
367 CallNode(classDef->Body());
368 }
369
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const370 void ScopesInitPhase::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
371 {
372 util::ErrorHandler::ThrowSyntaxError(Program(), errorMessage, pos);
373 }
374
CreateFuncDecl(ir::ScriptFunction * func)375 void ScopesInitPhase::CreateFuncDecl(ir::ScriptFunction *func)
376 {
377 AddOrGetDecl<varbinder::FunctionDecl>(VarBinder(), func->Id()->Name(), func, func->Id()->Start(), Allocator(),
378 func->Id()->Name(), func);
379 }
380
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)381 util::StringView ScopesInitPhase::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
382 {
383 return id->Name();
384 }
385
BindClassName(ir::ClassDefinition * classDef)386 varbinder::Decl *ScopesInitPhase::BindClassName(ir::ClassDefinition *classDef)
387 {
388 const auto identNode = classDef->Ident();
389 if (identNode == nullptr) {
390 return nullptr;
391 }
392
393 auto identDecl = AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), identNode->Name(), classDef, identNode->Start(),
394 identNode->Name());
395 if (identDecl != nullptr) {
396 identDecl->BindNode(classDef);
397 }
398 return identDecl;
399 }
400
BindFunctionScopes(varbinder::FunctionScope * scope,varbinder::FunctionParamScope * paramScope)401 void ScopesInitPhase::BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope)
402 {
403 scope->BindParamScope(paramScope);
404 paramScope->BindFunctionScope(scope);
405 }
406
BindClassDefinition(ir::ClassDefinition * classDef)407 void ScopesInitPhase::BindClassDefinition(ir::ClassDefinition *classDef)
408 {
409 if (classDef->IsGlobal()) {
410 return; // We handle it in ClassDeclaration
411 }
412 const auto locStart = classDef->Ident()->Start();
413 const auto &className = classDef->Ident()->Name();
414 if ((classDef->Modifiers() & ir::ClassDefinitionModifiers::CLASS_DECL) != 0U) {
415 AddOrGetDecl<varbinder::ClassDecl>(VarBinder(), className, classDef, locStart, className, classDef);
416 } else {
417 AddOrGetDecl<varbinder::LetDecl>(VarBinder(), className, classDef, locStart, className, classDef);
418 }
419 }
420
AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,lexer::SourcePosition startLoc,const ir::Identifier * id)421 std::tuple<varbinder::Decl *, varbinder::Variable *> ScopesInitPhase::AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,
422 lexer::SourcePosition startLoc,
423 const ir::Identifier *id)
424 {
425 if (auto var = id->Variable(); var != nullptr) {
426 return {var->Declaration(), var};
427 }
428 auto name = id->Name();
429 switch (flag) {
430 case ir::VariableDeclaratorFlag::LET:
431 return VarBinder()->NewVarDecl<varbinder::LetDecl>(startLoc, name);
432 case ir::VariableDeclaratorFlag::VAR:
433 return VarBinder()->NewVarDecl<varbinder::VarDecl>(startLoc, name);
434 case ir::VariableDeclaratorFlag::CONST:
435 return VarBinder()->NewVarDecl<varbinder::ConstDecl>(startLoc, name);
436 default:
437 UNREACHABLE();
438 }
439 }
440
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)441 void ScopesInitPhase::BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
442 [[maybe_unused]] varbinder::Variable *var)
443 {
444 decl->BindNode(init);
445 }
446
AttachLabelToScope(ir::AstNode * node)447 void ScopesInitPhase::AttachLabelToScope([[maybe_unused]] ir::AstNode *node) {}
448
VisitFunctionExpression(ir::FunctionExpression * funcExpr)449 void ScopesInitPhase::VisitFunctionExpression(ir::FunctionExpression *funcExpr)
450 {
451 Iterate(funcExpr);
452 if (!funcExpr->IsAnonymous()) {
453 auto func = funcExpr->Function();
454 auto id = funcExpr->Id();
455 auto *funcParamScope = func->Scope()->ParamScope();
456 funcParamScope->BindName(Allocator(), id->Name());
457 func->SetIdent(id->Clone(Allocator(), nullptr));
458 }
459 }
460
Prepare(ScopesInitPhase::PhaseContext * ctx,parser::Program * program)461 void ScopesInitPhase::Prepare(ScopesInitPhase::PhaseContext *ctx, parser::Program *program)
462 {
463 ctx_ = ctx;
464 program_ = program;
465 }
466
Finalize()467 void ScopesInitPhase::Finalize()
468 {
469 AnalyzeExports();
470 }
471
AnalyzeExports()472 void ScopesInitPhase::AnalyzeExports()
473 {
474 if (Program()->Kind() == parser::ScriptKind::MODULE && VarBinder()->TopScope()->IsModuleScope() &&
475 !VarBinder()->TopScope()->AsModuleScope()->ExportAnalysis()) {
476 ThrowSyntaxError("Invalid exported binding", Program()->Ast()->End());
477 }
478 }
479
VisitTSModuleDeclaration(ir::TSModuleDeclaration * moduleDecl)480 void ScopeInitTyped::VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl)
481 {
482 if (!moduleDecl->IsExternalOrAmbient()) {
483 auto name = moduleDecl->Name()->AsIdentifier()->Name();
484 auto *decl = AddOrGetDecl<varbinder::VarDecl>(VarBinder(), name, moduleDecl, moduleDecl->Name()->Start(), name);
485 decl->BindNode(moduleDecl);
486 }
487 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), moduleDecl);
488 BindScopeNode(localCtx.GetScope(), moduleDecl);
489 Iterate(moduleDecl);
490 }
491
VisitTSModuleBlock(ir::TSModuleBlock * block)492 void ScopeInitTyped::VisitTSModuleBlock(ir::TSModuleBlock *block)
493 {
494 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), block);
495 Iterate(block);
496 BindScopeNode(localCtx.GetScope(), block);
497 }
498
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAliasDecl)499 void ScopeInitTyped::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl)
500 {
501 const auto id = typeAliasDecl->Id();
502 varbinder::TSBinding tsBinding(Allocator(), id->Name());
503 auto *decl = VarBinder()->AddTsDecl<varbinder::TypeAliasDecl>(id->Start(), tsBinding.View());
504 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAliasDecl->TypeParams());
505 decl->BindNode(typeAliasDecl);
506 Iterate(typeAliasDecl);
507 }
508
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)509 util::StringView ScopeInitTyped::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
510 {
511 varbinder::TSBinding tsBinding(Allocator(), id->Name());
512 return tsBinding.View();
513 }
514
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfDecl)515 void ScopeInitTyped::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl)
516 {
517 const auto &bindings = VarBinder()->GetScope()->Bindings();
518 const auto ident = interfDecl->Id();
519 const auto name = FormInterfaceOrEnumDeclarationIdBinding(ident);
520 auto res = bindings.find(name);
521
522 varbinder::InterfaceDecl *decl {};
523
524 bool alreadyExists = false;
525 if (res == bindings.end()) {
526 decl = VarBinder()->AddTsDecl<varbinder::InterfaceDecl>(ident->Start(), Allocator(), name);
527 } else if (!AllowInterfaceRedeclaration()) {
528 ThrowSyntaxError("Interface redeclaration is not allowed", interfDecl->Start());
529 } else if (!res->second->Declaration()->IsInterfaceDecl()) {
530 VarBinder()->ThrowRedeclaration(ident->Start(), ident->Name());
531 } else {
532 decl = res->second->Declaration()->AsInterfaceDecl();
533 alreadyExists = true;
534 }
535
536 CallNode(ident);
537 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl->TypeParams());
538 CallNode(interfDecl->TypeParams());
539 CallNode(interfDecl->Extends());
540
541 auto localScope = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl);
542 auto *identDecl =
543 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), ident->Name(), interfDecl, ident->Start(), ident->Name());
544 identDecl->BindNode(interfDecl);
545 BindScopeNode(localScope.GetScope(), interfDecl);
546
547 CallNode(interfDecl->Body());
548 if (!alreadyExists) {
549 decl->BindNode(interfDecl);
550 }
551 decl->Add(interfDecl);
552 }
553
VisitTSEnumMember(ir::TSEnumMember * enumMember)554 void ScopeInitTyped::VisitTSEnumMember(ir::TSEnumMember *enumMember)
555 {
556 const auto key = enumMember->Key();
557 util::StringView name;
558 if (key->IsIdentifier()) {
559 name = key->AsIdentifier()->Name();
560 } else if (key->IsStringLiteral()) {
561 name = key->AsStringLiteral()->Str();
562 } else {
563 UNREACHABLE();
564 }
565 auto *decl = AddOrGetDecl<varbinder::EnumDecl>(VarBinder(), name, enumMember, key->Start(), name);
566 decl->BindNode(enumMember);
567 }
568
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)569 void ScopeInitTyped::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
570 {
571 util::StringView ident = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
572 const auto &bindings = VarBinder()->GetScope()->Bindings();
573 auto res = bindings.find(ident);
574
575 varbinder::EnumLiteralDecl *decl {};
576 if (res == bindings.end()) {
577 decl = VarBinder()->AddTsDecl<varbinder::EnumLiteralDecl>(enumDecl->Start(), ident, enumDecl->IsConst());
578 varbinder::LexicalScope enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
579 decl->BindScope(enumCtx.GetScope());
580 BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), enumDecl);
581 } else if (!res->second->Declaration()->IsEnumLiteralDecl() ||
582 (enumDecl->IsConst() ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst()) != 0) {
583 auto loc = enumDecl->Key()->End();
584 loc.index++;
585 VarBinder()->ThrowRedeclaration(loc, enumDecl->Key()->Name());
586 } else {
587 decl = res->second->Declaration()->AsEnumLiteralDecl();
588
589 auto scopeCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), decl->Scope());
590 }
591 decl->BindNode(enumDecl);
592 Iterate(enumDecl);
593 }
594
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)595 void ScopeInitTyped::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
596 {
597 auto name = typeParam->Name()->Name();
598 auto decl = AddOrGetDecl<varbinder::TypeParameterDecl>(VarBinder(), name, typeParam, typeParam->Start(), name);
599 decl->BindNode(typeParam);
600 Iterate(typeParam);
601 }
602
VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration * paramDecl)603 void ScopeInitTyped::VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl)
604 {
605 BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl);
606 Iterate(paramDecl);
607 }
608
VisitClassDefinition(ir::ClassDefinition * classDef)609 void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef)
610 {
611 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
612 CallNode(classDef->TypeParams());
613
614 auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
615 BindClassName(classDef);
616 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
617 classDef->PrivateId());
618 BindScopeNode(classCtx.GetScope(), classDef);
619 IterateNoTParams(classDef);
620 }
621
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)622 void InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
623 {
624 ExportDeclarationContext exportDeclCtx(VarBinder());
625 Iterate(exportDecl);
626 }
627
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)628 void InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
629 {
630 ExportDeclarationContext exportDeclCtx(VarBinder());
631 Iterate(exportDecl);
632 }
633
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)634 void InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
635 {
636 ImportDeclarationContext importCtx(VarBinder());
637 Iterate(importDeclaration);
638 }
639
VisitTSFunctionType(ir::TSFunctionType * constrType)640 void InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType)
641 {
642 auto lexicalScope =
643 (constrType->Scope() == nullptr)
644 ? HandleFunctionSig(constrType->TypeParams(), constrType->Params(), constrType->ReturnType())
645 : constrType->Scope();
646 BindScopeNode(lexicalScope, constrType);
647 }
648
CreateFuncDecl(ir::ScriptFunction * func)649 void InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func)
650 {
651 const auto identNode = func->Id();
652 const auto startLoc = identNode->Start();
653 const auto &bindings = VarBinder()->GetScope()->Bindings();
654 auto res = bindings.find(identNode->Name());
655 varbinder::FunctionDecl *decl {};
656
657 if (res == bindings.end()) {
658 decl = VarBinder()->AddDecl<varbinder::FunctionDecl>(startLoc, Allocator(), identNode->Name(), func);
659 } else {
660 varbinder::Decl *currentDecl = res->second->Declaration();
661
662 auto &existing = currentDecl->AsFunctionDecl()->Decls();
663 if (std::find(existing.begin(), existing.end(), func) != existing.end()) {
664 return;
665 }
666
667 if (!currentDecl->IsFunctionDecl() ||
668 !currentDecl->AsFunctionDecl()->Node()->AsScriptFunction()->IsOverload()) {
669 VarBinder()->ThrowRedeclaration(startLoc, currentDecl->Name());
670 }
671 decl = currentDecl->AsFunctionDecl();
672 }
673
674 decl->Add(func);
675 }
676
VisitTSConstructorType(ir::TSConstructorType * constrT)677 void InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT)
678 {
679 auto funcParamScope = (constrT->Scope() == nullptr)
680 ? HandleFunctionSig(constrT->TypeParams(), constrT->Params(), constrT->ReturnType())
681 : constrT->Scope();
682 BindScopeNode(funcParamScope, constrT);
683 }
684
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowFExpr)685 void InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr)
686 {
687 auto typeParamsCtx =
688 LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), arrowFExpr->Function()->TypeParams());
689 Iterate(arrowFExpr);
690 }
691
VisitTSSignatureDeclaration(ir::TSSignatureDeclaration * signDecl)692 void InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl)
693 {
694 auto funcParamScope = (signDecl->Scope() == nullptr) ? HandleFunctionSig(signDecl->TypeParams(), signDecl->Params(),
695 signDecl->ReturnTypeAnnotation())
696 : signDecl->Scope();
697 BindScopeNode(funcParamScope, signDecl);
698 }
699
VisitTSMethodSignature(ir::TSMethodSignature * methodSign)700 void InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign)
701 {
702 auto funcParamScope =
703 (methodSign->Scope() == nullptr)
704 ? HandleFunctionSig(methodSign->TypeParams(), methodSign->Params(), methodSign->ReturnTypeAnnotation())
705 : methodSign->Scope();
706 BindScopeNode(funcParamScope, methodSign);
707 }
708
RunExternalNode(ir::AstNode * node,varbinder::VarBinder * varbinder)709 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder)
710 {
711 auto program = parser::Program(varbinder->Allocator(), varbinder);
712 RunExternalNode(node, &program);
713 }
714
RunExternalNode(ir::AstNode * node,parser::Program * ctx)715 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx)
716 {
717 auto scopesPhase = InitScopesPhaseETS();
718 scopesPhase.SetProgram(ctx);
719 scopesPhase.CallNode(node);
720 }
721
Perform(PhaseContext * ctx,parser::Program * program)722 bool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program)
723 {
724 Prepare(ctx, program);
725
726 if (program->VarBinder()->TopScope() == nullptr) {
727 program->VarBinder()->InitTopScope();
728 BindScopeNode(GetScope(), program->Ast());
729 AddGlobalToBinder(program);
730 }
731 HandleProgram(program);
732 Finalize();
733 return true;
734 }
735
HandleProgram(parser::Program * program)736 void InitScopesPhaseETS::HandleProgram(parser::Program *program)
737 {
738 for (auto &[_, prog_list] : program->ExternalSources()) {
739 (void)_;
740 auto savedTopScope(program->VarBinder()->TopScope());
741 auto mainProg = prog_list.front();
742 mainProg->VarBinder()->InitTopScope();
743 AddGlobalToBinder(mainProg);
744 BindScopeNode(mainProg->VarBinder()->GetScope(), mainProg->Ast());
745 auto globalClass = mainProg->GlobalClass();
746 auto globalScope = mainProg->GlobalScope();
747 for (auto &prog : prog_list) {
748 prog->SetGlobalClass(globalClass);
749 BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast());
750 prog->VarBinder()->ResetTopScope(globalScope);
751 if (mainProg->Ast() != nullptr) {
752 InitScopesPhaseETS().Perform(Context(), prog);
753 }
754 }
755 program->VarBinder()->ResetTopScope(savedTopScope);
756 }
757 ASSERT(program->Ast() != nullptr);
758
759 HandleETSScript(program->Ast());
760 }
761
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)762 void InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
763 varbinder::Variable *var)
764 {
765 binding->SetVariable(var);
766 var->SetScope(VarBinder()->GetScope());
767 var->AddFlag(varbinder::VariableFlags::LOCAL);
768 decl->BindNode(init);
769 }
770
VisitBlockExpression(ir::BlockExpression * blockExpr)771 void InitScopesPhaseETS::VisitBlockExpression(ir::BlockExpression *blockExpr)
772 {
773 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), blockExpr);
774 if (blockExpr->Scope() == nullptr) {
775 BindScopeNode(GetScope(), blockExpr);
776 }
777 Iterate(blockExpr);
778 }
779
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)780 void InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
781 {
782 const auto func = staticBlock->Function();
783
784 {
785 auto funcParamCtx = (func->Scope() == nullptr)
786 ? varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder())
787 : varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(
788 VarBinder(), func->Scope()->ParamScope());
789 auto *funcParamScope = funcParamCtx.GetScope();
790 auto funcCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), func);
791 auto *funcScope = funcCtx.GetScope();
792
793 func->Body()->AsBlockStatement()->SetScope(funcScope);
794 BindScopeNode(funcScope, func);
795 funcParamScope->BindNode(func);
796 BindFunctionScopes(funcScope, funcParamScope);
797 Iterate(func->Body()->AsBlockStatement());
798 }
799
800 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
801 VarBinder(), VarBinder()->GetScope()->AsClassScope()->StaticMethodScope());
802
803 if (func->Id()->Variable() != nullptr) {
804 return;
805 }
806
807 auto [_, var] = VarBinder()->NewVarDecl<varbinder::FunctionDecl>(staticBlock->Start(), Allocator(),
808 func->Id()->Name(), staticBlock);
809 (void)_;
810 var->AddFlag(varbinder::VariableFlags::METHOD);
811 func->Id()->SetVariable(var);
812 }
813
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)814 void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
815 {
816 if (importSpec->Local()->Name().Empty()) {
817 return;
818 }
819 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
820 importSpec->Local()->Name(), importSpec->Local()->Name(), importSpec);
821 auto var =
822 VarBinder()->GetScope()->FindLocal(importSpec->Local()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
823 importSpec->Local()->SetVariable(var);
824 Iterate(importSpec);
825 }
826
VisitImportSpecifier(ir::ImportSpecifier * importSpec)827 void InitScopesPhaseETS::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
828 {
829 if (importSpec->Parent()->AsETSImportDeclaration()->IsPureDynamic()) {
830 auto [decl, var] =
831 VarBinder()->NewVarDecl<varbinder::LetDecl>(importSpec->Start(), importSpec->Local()->Name(), importSpec);
832 var->AddFlag(varbinder::VariableFlags::INITIALIZED);
833 }
834 Iterate(importSpec);
835 }
836
837 // Auxiliary method to avoid extra nested levels and too large function size
AddOverload(ir::MethodDefinition * overload,varbinder::Variable * variable)838 void AddOverload(ir::MethodDefinition *overload, varbinder::Variable *variable) noexcept
839 {
840 auto *currentNode = variable->Declaration()->Node();
841 currentNode->AsMethodDefinition()->AddOverload(overload);
842 overload->Id()->SetVariable(variable);
843 overload->SetParent(currentNode);
844 }
845
DeclareClassMethod(ir::MethodDefinition * method)846 void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method)
847 {
848 ASSERT(VarBinder()->GetScope()->IsClassScope());
849
850 if ((method->AsMethodDefinition()->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0) {
851 return;
852 }
853
854 const auto methodName = method->Id();
855 auto *const clsScope = VarBinder()->GetScope()->AsClassScope();
856 auto options =
857 method->IsStatic()
858 ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION
859 : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION;
860 if (clsScope->FindLocal(methodName->Name(), options) != nullptr) {
861 VarBinder()->ThrowRedeclaration(methodName->Start(), methodName->Name());
862 }
863
864 varbinder::LocalScope *targetScope {};
865 if (method->IsStatic() || method->IsConstructor()) {
866 targetScope = clsScope->StaticMethodScope();
867 } else {
868 targetScope = clsScope->InstanceMethodScope();
869 }
870 auto *found = targetScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::BINDINGS);
871
872 MaybeAddOverload(method, methodName, found, clsScope, targetScope);
873 }
874
MaybeAddOverload(ir::MethodDefinition * method,ir::Identifier * methodName,varbinder::Variable * found,varbinder::ClassScope * clsScope,varbinder::LocalScope * targetScope)875 void InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName,
876 varbinder::Variable *found, varbinder::ClassScope *clsScope,
877 varbinder::LocalScope *targetScope)
878 {
879 if (found == nullptr) {
880 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), targetScope);
881
882 auto *var = methodName->Variable();
883 if (var == nullptr) {
884 var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(methodName->Start(), Allocator(),
885 methodName->Name(), method));
886 var->SetScope(clsScope);
887 var->AddFlag(varbinder::VariableFlags::METHOD);
888 methodName->SetVariable(var);
889 }
890 for (auto *overload : method->Overloads()) {
891 ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
892 overload->Id()->SetVariable(var);
893 overload->SetParent(var->Declaration()->Node());
894 }
895 } else {
896 if (methodName->Name().Is(compiler::Signatures::MAIN) && clsScope->Parent()->IsGlobalScope()) {
897 ThrowSyntaxError("Main overload is not enabled", methodName->Start());
898 }
899 AddOverload(method, found);
900 method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
901
902 // default params overloads
903 for (auto *overload : method->Overloads()) {
904 ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
905 AddOverload(overload, found);
906 }
907 method->ClearOverloads();
908 }
909 }
910
VisitETSReExportDeclaration(ir::ETSReExportDeclaration * reExport)911 void InitScopesPhaseETS::VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport)
912 {
913 if (reExport->GetETSImportDeclarations()->Language().IsDynamic()) {
914 VarBinder()->AsETSBinder()->AddDynamicImport(reExport->GetETSImportDeclarations());
915 }
916 VarBinder()->AsETSBinder()->AddReExportImport(reExport);
917 }
918
VisitETSParameterExpression(ir::ETSParameterExpression * paramExpr)919 void InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr)
920 {
921 auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramExpr));
922 paramExpr->Ident()->SetVariable(var);
923 var->SetScope(VarBinder()->GetScope());
924 Iterate(paramExpr);
925 }
926
VisitETSImportDeclaration(ir::ETSImportDeclaration * importDecl)927 void InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl)
928 {
929 ImportDeclarationContext importCtx(VarBinder());
930 if (importDecl->Language().IsDynamic()) {
931 VarBinder()->AsETSBinder()->AddDynamicImport(importDecl);
932 }
933 Iterate(importDecl);
934 }
935
VisitTSEnumMember(ir::TSEnumMember * enumMember)936 void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember)
937 {
938 auto ident = enumMember->Key()->AsIdentifier();
939 if (ident->Variable() != nullptr) {
940 return;
941 }
942 auto [decl, var] = VarBinder()->NewVarDecl<varbinder::LetDecl>(ident->Start(), ident->Name());
943 var->SetScope(VarBinder()->GetScope());
944 var->AddFlag(varbinder::VariableFlags::STATIC);
945 ident->SetVariable(var);
946 decl->BindNode(enumMember);
947 Iterate(enumMember);
948 }
949
VisitMethodDefinition(ir::MethodDefinition * method)950 void InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method)
951 {
952 auto *curScope = VarBinder()->GetScope();
953 const auto methodName = method->Id();
954 auto res =
955 curScope->Find(methodName->Name(), method->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
956 : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
957 if (res.variable != nullptr && !res.variable->Declaration()->IsFunctionDecl() && res.scope == curScope) {
958 VarBinder()->ThrowRedeclaration(methodName->Start(), res.name);
959 }
960 Iterate(method);
961 DeclareClassMethod(method);
962 }
963
VisitETSFunctionType(ir::ETSFunctionType * funcType)964 void InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType)
965 {
966 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), funcType->TypeParams());
967
968 // Check for existing scope
969 // In some cases we can visit function again with scope that already exists
970 // Example: async lambda, we "move" original function to another place and visit it again
971 if (funcType->Scope() == nullptr) {
972 varbinder::LexicalScope<varbinder::FunctionParamScope> lexicalScope(VarBinder());
973 auto *funcParamScope = lexicalScope.GetScope();
974 BindScopeNode(funcParamScope, funcType);
975 Iterate(funcType);
976 }
977 }
978
VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression * newClassExpr)979 void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr)
980 {
981 CallNode(newClassExpr->GetArguments());
982 CallNode(newClassExpr->GetTypeRef());
983 if (newClassExpr->ClassDefinition() != nullptr) {
984 const auto classDef = newClassExpr->ClassDefinition();
985 auto *parentClassScope = VarBinder()->GetScope();
986 while (!parentClassScope->IsClassScope()) {
987 ASSERT(parentClassScope->Parent());
988 parentClassScope = parentClassScope->Parent();
989 }
990 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), newClassExpr->ClassDefinition());
991 util::UString anonymousName(util::StringView("#"), Allocator());
992 anonymousName.Append(std::to_string(parentClassScope->AsClassScope()->GetAndIncrementAnonymousClassIdx()));
993 classDef->SetInternalName(anonymousName.View());
994 classDef->Ident()->SetName(anonymousName.View());
995 CallNode(classDef);
996 }
997 }
998
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)999 void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
1000 {
1001 if (typeParam->Name()->Variable() != nullptr) {
1002 return;
1003 }
1004 auto [decl, var] =
1005 VarBinder()->NewVarDecl<varbinder::TypeParameterDecl>(typeParam->Name()->Start(), typeParam->Name()->Name());
1006 typeParam->Name()->SetVariable(var);
1007 var->SetScope(VarBinder()->GetScope());
1008 var->AddFlag(varbinder::VariableFlags::TYPE_PARAMETER);
1009 decl->BindNode(typeParam);
1010 }
1011
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfaceDecl)1012 void InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl)
1013 {
1014 {
1015 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfaceDecl->TypeParams());
1016 CallNode(interfaceDecl->TypeParams());
1017 CallNode(interfaceDecl->Extends());
1018 auto localScope = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), interfaceDecl);
1019 CallNode(interfaceDecl->Body());
1020 BindScopeNode(localScope.GetScope(), interfaceDecl);
1021 }
1022 auto name = FormInterfaceOrEnumDeclarationIdBinding(interfaceDecl->Id());
1023 auto *decl = AddOrGetDecl<varbinder::InterfaceDecl>(VarBinder(), name, interfaceDecl, interfaceDecl->Start(),
1024 Allocator(), name, interfaceDecl);
1025 decl->AsInterfaceDecl()->Add(interfaceDecl);
1026 }
1027
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)1028 void InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
1029 {
1030 {
1031 const auto enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
1032 BindScopeNode(enumCtx.GetScope(), enumDecl);
1033 Iterate(enumDecl);
1034 }
1035 auto name = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
1036 auto *decl = AddOrGetDecl<varbinder::EnumLiteralDecl>(VarBinder(), name, enumDecl, enumDecl->Start(), name,
1037 enumDecl, enumDecl->IsConst());
1038 decl->BindScope(enumDecl->Scope());
1039 }
1040
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAlias)1041 void InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias)
1042 {
1043 AddOrGetDecl<varbinder::TypeAliasDecl>(VarBinder(), typeAlias->Id()->Name(), typeAlias, typeAlias->Id()->Start(),
1044 typeAlias->Id()->Name(), typeAlias);
1045 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAlias->TypeParams());
1046 Iterate(typeAlias);
1047 }
1048
AddGlobalToBinder(parser::Program * program)1049 void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program)
1050 {
1051 auto globalId = program->GlobalClass()->Ident();
1052 if (globalId->Variable() != nullptr) {
1053 return;
1054 }
1055
1056 auto [decl2, var] = program->VarBinder()->NewVarDecl<varbinder::ClassDecl>(globalId->Start(), globalId->Name());
1057
1058 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(program->VarBinder(), program->GlobalClass());
1059 classCtx.GetScope()->BindNode(program->GlobalClass());
1060 program->GlobalClass()->SetScope(classCtx.GetScope());
1061
1062 auto *classDecl = program->GlobalClass()->Parent();
1063 decl2->BindNode(classDecl);
1064 globalId->SetVariable(var);
1065 }
1066
HandleETSScript(ir::BlockStatement * script)1067 void InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script)
1068 {
1069 for (auto decl : script->Statements()) {
1070 if (decl->IsETSImportDeclaration()) {
1071 CallNode(decl);
1072 } else {
1073 auto classCtx =
1074 varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1075 CallNode(decl);
1076 }
1077 }
1078 auto classCtx = varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1079
1080 for (auto decl : script->Statements()) {
1081 AddGlobalDeclaration(decl);
1082 }
1083 }
1084
VisitClassDefinition(ir::ClassDefinition * classDef)1085 void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef)
1086 {
1087 if (classDef->IsGlobal()) {
1088 ParseGlobalClass(classDef);
1089 return;
1090 }
1091 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
1092 CallNode(classDef->TypeParams());
1093 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), classDef);
1094
1095 IterateNoTParams(classDef);
1096 FilterOverloads(classDef->Body());
1097 auto *classScope = classCtx.GetScope();
1098 BindScopeNode(classScope, classDef);
1099 }
1100
VisitTSInterfaceBody(ir::TSInterfaceBody * interfBody)1101 void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody)
1102 {
1103 Iterate(interfBody);
1104 FilterInterfaceOverloads(interfBody->Body());
1105 }
1106
FilterInterfaceOverloads(ArenaVector<ir::AstNode *,false> & props)1107 void InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector<ir::AstNode *, false> &props)
1108 {
1109 auto condition = [](ir::AstNode *prop) {
1110 if (prop->IsMethodDefinition()) {
1111 const auto func = prop->AsMethodDefinition()->Function();
1112 return func->IsOverload() && func->Body() != nullptr;
1113 }
1114 return false;
1115 };
1116 props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1117 }
1118
FilterOverloads(ArenaVector<ir::AstNode *,false> & props)1119 void InitScopesPhaseETS::FilterOverloads(ArenaVector<ir::AstNode *, false> &props)
1120 {
1121 auto condition = [](ir::AstNode *prop) {
1122 if (prop->IsMethodDefinition()) {
1123 const auto func = prop->AsMethodDefinition()->Function();
1124 return func->IsOverload();
1125 }
1126 return false;
1127 };
1128 props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1129 }
1130
VisitClassProperty(ir::ClassProperty * classProp)1131 void InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *classProp)
1132 {
1133 auto curScope = VarBinder()->GetScope();
1134 const auto name = classProp->Key()->AsIdentifier()->Name();
1135 if (classProp->IsClassStaticBlock()) {
1136 ASSERT(curScope->IsClassScope());
1137 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
1138 VarBinder(), curScope->AsClassScope()->StaticMethodScope());
1139 auto *var = classProp->Id()->Variable();
1140 if (var == nullptr) {
1141 var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(classProp->Start(), Allocator(),
1142 classProp->Id()->Name(), classProp));
1143 }
1144 var->AddFlag(varbinder::VariableFlags::METHOD);
1145 classProp->AsClassStaticBlock()->Function()->Id()->SetVariable(var);
1146 } else if (classProp->IsConst()) {
1147 ASSERT(curScope->Parent() != nullptr);
1148 const auto initializer = classProp->Value();
1149 if (initializer == nullptr && curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare()) {
1150 auto pos = classProp->End();
1151 // NOTE: Just use property Name?
1152 if (!classProp->TypeAnnotation()->IsETSPrimitiveType()) {
1153 pos.index--;
1154 }
1155 ThrowSyntaxError("Missing initializer in const declaration", pos);
1156 }
1157 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1158 } else if (classProp->IsReadonly()) {
1159 ASSERT(curScope->Parent() != nullptr);
1160 if (curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare()) {
1161 auto pos = classProp->End();
1162 ThrowSyntaxError("Readonly field cannot be in Global scope", pos);
1163 }
1164 AddOrGetDecl<varbinder::ReadonlyDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1165 } else {
1166 AddOrGetDecl<varbinder::LetDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1167 }
1168 Iterate(classProp);
1169 }
1170
VisitBreakStatement(ir::BreakStatement * stmt)1171 void InitScopesPhaseETS::VisitBreakStatement(ir::BreakStatement *stmt)
1172 {
1173 auto label = stmt->Ident();
1174 if (label != nullptr) {
1175 auto scope = VarBinder()->GetScope();
1176 auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1177 label->SetVariable(var);
1178 }
1179 }
1180
VisitContinueStatement(ir::ContinueStatement * stmt)1181 void InitScopesPhaseETS::VisitContinueStatement(ir::ContinueStatement *stmt)
1182 {
1183 auto label = stmt->Ident();
1184 if (label != nullptr) {
1185 auto scope = VarBinder()->GetScope();
1186 auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1187 label->SetVariable(var);
1188 }
1189 }
1190
AttachLabelToScope(ir::AstNode * node)1191 void InitScopesPhaseETS::AttachLabelToScope(ir::AstNode *node)
1192 {
1193 if (node->Parent() == nullptr) {
1194 return;
1195 }
1196
1197 if (!node->Parent()->IsLabelledStatement()) {
1198 return;
1199 }
1200
1201 auto stmt = node->Parent()->AsLabelledStatement();
1202 auto label = stmt->Ident();
1203 if (label == nullptr) {
1204 return;
1205 }
1206
1207 auto decl = AddOrGetDecl<varbinder::LabelDecl>(VarBinder(), label->Name(), stmt, label->Start(), label->Name());
1208 decl->BindNode(stmt);
1209
1210 auto var = VarBinder()->GetScope()->FindLocal(label->Name(), varbinder::ResolveBindingOptions::BINDINGS);
1211 if (var != nullptr) {
1212 label->SetVariable(var);
1213 var->SetScope(VarBinder()->GetScope());
1214 var->AddFlag(varbinder::VariableFlags::LOCAL);
1215 }
1216 }
1217
ParseGlobalClass(ir::ClassDefinition * global)1218 void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global)
1219 {
1220 for (auto decl : global->Body()) {
1221 if (decl->IsDefaultExported()) {
1222 if (VarBinder()->AsETSBinder()->DefaultExport() != nullptr) {
1223 ThrowSyntaxError("Only one default export is allowed in a module", decl->Start());
1224 }
1225 VarBinder()->AsETSBinder()->SetDefaultExport(decl);
1226 }
1227 CallNode(decl);
1228 }
1229 FilterOverloads(global->Body());
1230 }
1231
AddGlobalDeclaration(ir::AstNode * node)1232 void InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node)
1233 {
1234 ir::Identifier *ident = nullptr;
1235 bool isBuiltin = false;
1236 switch (node->Type()) {
1237 case ir::AstNodeType::CLASS_DECLARATION: {
1238 auto def = node->AsClassDeclaration()->Definition();
1239 if (def->IsGlobal()) {
1240 return;
1241 }
1242 ident = def->Ident();
1243 isBuiltin = def->IsFromExternal();
1244 break;
1245 }
1246 case ir::AstNodeType::STRUCT_DECLARATION: {
1247 ident = node->AsETSStructDeclaration()->Definition()->Ident();
1248 isBuiltin = node->AsETSStructDeclaration()->Definition()->IsFromExternal();
1249 break;
1250 }
1251 case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
1252 ident = node->AsTSInterfaceDeclaration()->Id();
1253 isBuiltin = node->AsTSInterfaceDeclaration()->IsFromExternal();
1254 break;
1255 }
1256 case ir::AstNodeType::TS_ENUM_DECLARATION: {
1257 ident = node->AsTSEnumDeclaration()->Key();
1258 break;
1259 }
1260 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
1261 ident = node->AsTSTypeAliasDeclaration()->Id();
1262 break;
1263 }
1264 default: {
1265 break;
1266 }
1267 }
1268 if (ident != nullptr) {
1269 VarBinder()->TopScope()->InsertBinding(ident->Name(), ident->Variable());
1270 if (isBuiltin) {
1271 ident->Variable()->AddFlag(varbinder::VariableFlags::BUILTIN_TYPE);
1272 }
1273 }
1274 }
1275
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)1276 void InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
1277 {
1278 Iterate(arrowExpr);
1279 }
1280
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)1281 void InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
1282 {
1283 ExportDeclarationContext exportDeclCtx(VarBinder());
1284 Iterate(exportDecl);
1285 }
1286
1287 } // namespace ark::es2panda::compiler
1288