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