• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "transformer.h"
17 
18 #include "ir/base/scriptFunction.h"
19 #include "ir/base/classDefinition.h"
20 #include "ir/expressions/assignmentExpression.h"
21 #include "ir/expressions/binaryExpression.h"
22 #include "ir/expressions/callExpression.h"
23 #include "ir/expressions/functionExpression.h"
24 #include "ir/expressions/identifier.h"
25 #include "ir/expressions/memberExpression.h"
26 #include "ir/expressions/objectExpression.h"
27 #include "ir/module/exportNamedDeclaration.h"
28 #include "ir/statements/blockStatement.h"
29 #include "ir/statements/classDeclaration.h"
30 #include "ir/statements/emptyStatement.h"
31 #include "ir/statements/expressionStatement.h"
32 #include "ir/statements/functionDeclaration.h"
33 #include "ir/statements/variableDeclaration.h"
34 #include "ir/statements/variableDeclarator.h"
35 #include "ir/ts/tsImportEqualsDeclaration.h"
36 #include "ir/ts/tsModuleBlock.h"
37 #include "ir/ts/tsModuleDeclaration.h"
38 #include "ir/ts/tsQualifiedName.h"
39 #include "util/helpers.h"
40 
41 
42 namespace panda::es2panda::parser {
43 
Transform(Program * program)44 void Transformer::Transform(Program *program)
45 {
46     program_ = program;
47     if (Extension() == ScriptExtension::TS) {
48         TransformFromTS();
49     }
50 }
51 
TransformFromTS()52 void Transformer::TransformFromTS()
53 {
54     ASSERT(Extension() == ScriptExtension::TS);
55     VisitTSNodes(program_->Ast());
56 }
57 
VisitTSNodes(ir::AstNode * parent)58 ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent)
59 {
60     if (!parent) {
61         return nullptr;
62     }
63     parent->UpdateSelf([this](auto *childNode) { return VisitTSNode(childNode); }, Binder());
64     return parent;
65 }
66 
FindExportVariableInTsModuleScope(util::StringView name) const67 binder::Scope *Transformer::FindExportVariableInTsModuleScope(util::StringView name) const
68 {
69     bool isExport = false;
70     auto currentScope = Scope();
71     while (currentScope != nullptr) {
72         binder::Variable *v = currentScope->FindLocal(name, binder::ResolveBindingOptions::ALL);
73         bool isTSModuleScope = currentScope->IsTSModuleScope();
74         if (v != nullptr) {
75             if (!v->HasFlag(binder::VariableFlags::VAR)) {
76                 break;
77             }
78             if (isTSModuleScope && currentScope->AsTSModuleScope()->FindExportVariable(name)) {
79                 isExport = true;
80             }
81             break;
82         }
83         if (currentScope->InLocalTSBindings(name) &&
84             !currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name)) {
85             break;
86         }
87         if (isTSModuleScope && currentScope->AsTSModuleScope()->InExportBindings(name)) {
88             isExport = true;
89             break;
90         }
91         currentScope = currentScope->Parent();
92     }
93     if (!isExport) {
94         return nullptr;
95     }
96     return currentScope;
97 }
98 
VisitTSNode(ir::AstNode * childNode)99 ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode)
100 {
101     ASSERT(childNode != nullptr);
102     switch (childNode->Type()) {
103         case ir::AstNodeType::IDENTIFIER: {
104             auto *ident = childNode->AsIdentifier();
105             if (!ident->IsReference() || !IsTsModule()) {
106                 return VisitTSNodes(childNode);
107             }
108 
109             auto name = ident->Name();
110             auto scope = FindExportVariableInTsModuleScope(name);
111             if (scope) {
112                 auto moduleName = FindTSModuleNameByScope(scope);
113                 auto *id = AllocNode<ir::Identifier>(moduleName, Allocator());
114                 id->AsIdentifier()->SetReference();
115                 auto *res = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name, Allocator()),
116                     ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
117                 SetOriginalNode(res, childNode);
118                 return res;
119             }
120 
121             return VisitTSNodes(childNode);
122         }
123         case ir::AstNodeType::TS_MODULE_DECLARATION: {
124             auto *node = childNode->AsTSModuleDeclaration();
125             if (node->Declare() || !node->IsInstantiated()) {
126                 return childNode;
127             }
128             auto res = VisitTsModuleDeclaration(node);
129             SetOriginalNode(res, childNode);
130             return res;
131         }
132         case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
133             auto *node = childNode->AsExportNamedDeclaration();
134             auto *decl = node->Decl();
135             if (!decl) {
136                 return VisitTSNodes(childNode);
137             }
138 
139             if (decl->IsTSModuleDeclaration()) {
140                 auto *tsModuleDeclaration = decl->AsTSModuleDeclaration();
141                 if (tsModuleDeclaration->Declare() || !tsModuleDeclaration->IsInstantiated()) {
142                     return childNode;
143                 }
144                 auto res = VisitTsModuleDeclaration(tsModuleDeclaration, true);
145                 SetOriginalNode(res, childNode);
146                 return res;
147             }
148 
149             if (!IsTsModule()) {
150                 return VisitTSNodes(childNode);
151             }
152 
153             auto res = VisitExportNamedVariable(decl);
154             SetOriginalNode(res, childNode);
155             return res;
156         }
157         case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION: {
158             auto *node = childNode->AsTSImportEqualsDeclaration();
159             auto *express = node->ModuleReference();
160             if (express->IsTSExternalModuleReference()) {
161                 return VisitTSNodes(childNode);
162             }
163             auto *res = VisitTsImportEqualsDeclaration(node);
164             SetOriginalNode(res, childNode);
165             return res;
166         }
167         default: {
168             return VisitTSNodes(childNode);
169         }
170     }
171 }
172 
VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration * node)173 ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node)
174 {
175     auto *express = node->ModuleReference();
176     if (!IsInstantiatedTSModule(express)) {
177         return node;
178     }
179     auto name = node->Id()->Name();
180     if (IsTsModule() && node->IsExport()) {
181         auto moduleName = GetCurrentTSModuleName();
182         auto *id = AllocNode<ir::Identifier>(moduleName, Allocator());
183         id->AsIdentifier()->SetReference();
184         auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name, Allocator()),
185             ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
186         ir::Expression *right = CreateMemberExpressionFromQualified(express);
187         auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right,
188             lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
189         auto *res = AllocNode<ir::ExpressionStatement>(assignExpr);
190         return res;
191     }
192 
193     ir::Expression *init = CreateMemberExpressionFromQualified(express);
194     ir::Statement *res = CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::VAR, node,
195         node->IsExport(), init);
196     if (node->IsExport()) {
197         ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
198         res = AllocNode<ir::ExportNamedDeclaration>(res, std::move(specifiers));
199         AddExportLocalEntryItem(name, node->Id());
200     }
201     return res;
202 }
203 
IsInstantiatedTSModule(const ir::Expression * node) const204 bool Transformer::IsInstantiatedTSModule(const ir::Expression *node) const
205 {
206     auto *var = FindTSModuleVariable(node, Scope());
207     if (var == nullptr) {
208         return true;
209     }
210     auto *decl = var->Declaration();
211     ASSERT(decl->IsNamespaceDecl());
212     auto tsModules = decl->AsNamespaceDecl()->Decls();
213     for (auto *it : tsModules) {
214         if (it->IsInstantiated()) {
215             return true;
216         }
217     }
218     return false;
219 }
220 
FindTSModuleVariable(const ir::Expression * node,binder::Scope * scope) const221 binder::Variable *Transformer::FindTSModuleVariable(const ir::Expression *node, binder::Scope *scope) const
222 {
223     if (node == nullptr) {
224         return nullptr;
225     }
226     if (node->IsTSQualifiedName()) {
227         auto *tsQualifiedName = node->AsTSQualifiedName();
228         auto *var = FindTSModuleVariable(tsQualifiedName->Left(), scope);
229         if (var == nullptr) {
230             return nullptr;
231         }
232         auto *exportTSBindings = var->AsNamespaceVariable()->GetExportBindings();
233         auto name = tsQualifiedName->Right()->Name();
234         auto *res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
235         if (res != nullptr) {
236             return res;
237         }
238         res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
239         if (res != nullptr) {
240             auto *node = res->Declaration()->Node();
241             return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(),
242                 res->AsImportEqualsVariable()->GetScope());
243         }
244         return nullptr;
245     }
246     ASSERT(node->IsIdentifier());
247     auto name = node->AsIdentifier()->Name();
248     auto *currentScope = scope;
249     while (currentScope != nullptr) {
250         auto *res = currentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
251         if (res == nullptr && currentScope->IsTSModuleScope()) {
252             res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
253         }
254         if (res != nullptr) {
255             return res;
256         }
257         res = currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
258         if (res == nullptr && currentScope->IsTSModuleScope()) {
259             res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
260         }
261         if (res != nullptr) {
262             auto *node = res->Declaration()->Node();
263             return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(),
264                 res->AsImportEqualsVariable()->GetScope());
265         }
266         currentScope = currentScope->Parent();
267     }
268     return nullptr;
269 }
270 
VisitExportNamedVariable(ir::Statement * decl)271 std::vector<ir::AstNode *> Transformer::VisitExportNamedVariable(ir::Statement *decl)
272 {
273     std::vector<ir::AstNode *> res;
274     if (decl->IsVariableDeclaration()) {
275         auto declarators = decl->AsVariableDeclaration()->Declarators();
276         for (auto *it : declarators) {
277             if (it->Init()) {
278                 auto *left = std::get<ir::AstNode *>(VisitTSNode(it->Id()))->AsExpression();
279                 auto *right = std::get<ir::AstNode *>(VisitTSNode(it->Init()))->AsExpression();
280                 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right,
281                     lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
282                 res.push_back(AllocNode<ir::ExpressionStatement>(assignExpr));
283             }
284         }
285     } else if (decl->IsFunctionDeclaration() || decl->IsClassDeclaration()) {
286         res.push_back(VisitTSNodes(decl));
287         auto name = decl->IsFunctionDeclaration() ?
288             decl->AsFunctionDeclaration()->Function()->Id() :
289             decl->AsClassDeclaration()->Definition()->Ident();
290         ASSERT(name != nullptr);
291         res.push_back(CreateTsModuleAssignment(name->Name()));
292     }
293     return res;
294 }
295 
CreateMemberExpressionFromQualified(ir::Expression * node)296 ir::Expression *Transformer::CreateMemberExpressionFromQualified(ir::Expression *node)
297 {
298     if (node->IsTSQualifiedName()) {
299         auto *tsQualifiedName = node->AsTSQualifiedName();
300         auto *left = CreateMemberExpressionFromQualified(tsQualifiedName->Left());
301         auto *right = AllocNode<ir::Identifier>(tsQualifiedName->Right()->Name(), Allocator());
302         return AllocNode<ir::MemberExpression>(left, right,
303             ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
304     }
305     ASSERT(node->IsIdentifier());
306     auto *id = AllocNode<ir::Identifier>(node->AsIdentifier()->Name(), Allocator());
307     id->AsIdentifier()->SetReference();
308     return id;
309 }
310 
SetOriginalNode(ir::UpdateNodes res,ir::AstNode * originalNode) const311 void Transformer::SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const
312 {
313     if (std::holds_alternative<ir::AstNode *>(res)) {
314         auto *node = std::get<ir::AstNode *>(res);
315         if (node == nullptr || node == originalNode) {
316             return;
317         }
318         node->SetOriginal(originalNode);
319         node->SetRange(originalNode->Range());
320     } else {
321         auto nodes = std::get<std::vector<ir::AstNode *>>(res);
322         for (auto *it : nodes) {
323             it->SetOriginal(originalNode);
324             it->SetRange(originalNode->Range());
325         }
326     }
327 }
328 
CreateTsModuleAssignment(util::StringView name)329 ir::ExpressionStatement *Transformer::CreateTsModuleAssignment(util::StringView name)
330 {
331     auto moduleName = GetCurrentTSModuleName();
332     auto *id = AllocNode<ir::Identifier>(moduleName, Allocator());
333     id->AsIdentifier()->SetReference();
334     auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name, Allocator()),
335         ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
336     auto *right = AllocNode<ir::Identifier>(name, Allocator());
337     right->AsIdentifier()->SetReference();
338     auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
339     return AllocNode<ir::ExpressionStatement>(assignExpr);
340 }
341 
GetNameFromModuleDeclaration(ir::TSModuleDeclaration * node) const342 util::StringView Transformer::GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const
343 {
344     return node->Name()->AsIdentifier()->Name();
345 }
346 
CreateVariableDeclarationWithIdentify(util::StringView name,VariableParsingFlags flags,ir::AstNode * node,bool isExport,ir::Expression * init)347 ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util::StringView name,
348                                                                             VariableParsingFlags flags,
349                                                                             ir::AstNode *node,
350                                                                             bool isExport,
351                                                                             ir::Expression *init)
352 {
353     auto *ident = AllocNode<ir::Identifier>(name, Allocator());
354     ident->AsIdentifier()->SetReference();
355     auto *declarator = AllocNode<ir::VariableDeclarator>(ident, init);
356     ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
357     declarators.push_back(declarator);
358 
359     binder::Decl *decl = nullptr;
360     binder::DeclarationFlags declflag = isExport ?
361         binder::DeclarationFlags::EXPORT :
362         binder::DeclarationFlags::NONE;
363     auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
364     if (flags & VariableParsingFlags::VAR) {
365         decl = Binder()->AddDecl<binder::VarDecl>(node->Start(), declflag, name);
366     } else if (flags & VariableParsingFlags::LET) {
367         varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
368         decl = Binder()->AddDecl<binder::LetDecl>(node->Start(), declflag, name);
369     } else {
370         varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
371         decl = Binder()->AddDecl<binder::ConstDecl>(node->Start(), declflag, name);
372     }
373 
374     auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), false);
375     decl->BindNode(declaration);
376 
377     return declaration;
378 }
379 
GetParamName(ir::TSModuleDeclaration * node,util::StringView name) const380 util::StringView Transformer::GetParamName(ir::TSModuleDeclaration *node, util::StringView name) const
381 {
382     auto scope = node->Scope();
383     if (!scope->HasVariableName(name)) {
384         return name;
385     }
386 
387     auto pramaName = name;
388     uint32_t idx = 0;
389     do {
390         std::stringstream ss;
391         ss << name;
392         idx++;
393         ss << "_" << std::to_string(idx);
394         util::UString internalName(ss.str(), Allocator());
395         pramaName = internalName.View();
396     } while (Binder()->HasVariableName(pramaName));
397     Binder()->AddDeclarationName(pramaName);
398     return pramaName;
399 }
400 
CreateCallExpressionForTsModule(ir::TSModuleDeclaration * node,util::StringView name,bool isExport)401 ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node,
402                                                                  util::StringView name,
403                                                                  bool isExport)
404 {
405     ir::ScriptFunction *funcNode = nullptr;
406 
407     binder::FunctionScope *funcScope = node->Scope();
408     binder::FunctionParamScope *funcParamScope = funcScope->ParamScope();
409     auto paramName = GetParamName(node, name);
410     {
411         auto paramScopeCtx = binder::LexicalScope<binder::FunctionParamScope>::Enter(Binder(), funcParamScope);
412 
413         ArenaVector<ir::Expression *> params(Allocator()->Adapter());
414         auto *parameter = AllocNode<ir::Identifier>(paramName, Allocator());
415         parameter->AsIdentifier()->SetReference();
416         Binder()->AddParamDecl(parameter);
417         params.push_back(parameter);
418 
419         ir::BlockStatement *blockNode = nullptr;
420         {
421             auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), funcScope);
422             tsModuleList_.push_back({paramName, funcScope});
423             if (node->Body()->IsTSModuleDeclaration()) {
424                 auto *tsModule = node->Body()->AsTSModuleDeclaration();
425                 auto body = std::get<std::vector<ir::AstNode *>>(VisitTsModuleDeclaration(tsModule, true));
426                 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
427                 for (auto *it : body) {
428                     statements.push_back(static_cast<ir::Statement *>(it));
429                 }
430                 blockNode = AllocNode<ir::BlockStatement>(funcScope, std::move(statements));
431             } else {
432                 auto body = VisitTSNodes(node->Body());
433                 blockNode = AllocNode<ir::BlockStatement>(funcScope,
434                     std::move(body->AsTSModuleBlock()->Statements()));
435             }
436             tsModuleList_.pop_back();
437             funcScope->AddBindsFromParam();
438         }
439 
440         funcNode = AllocNode<ir::ScriptFunction>(funcScope, std::move(params), nullptr, blockNode, nullptr,
441             ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS);
442 
443         funcScope->BindNode(funcNode);
444         funcParamScope->BindNode(funcNode);
445     }
446 
447     auto *funcExpr = AllocNode<ir::FunctionExpression>(funcNode);
448 
449     ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
450     ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
451     auto *objectExpression = AllocNode<ir::ObjectExpression>(ir::AstNodeType::OBJECT_EXPRESSION,
452                                                              std::move(properties),
453                                                              false);
454     auto assignExpr = AllocNode<ir::AssignmentExpression>(CreateTsModuleParam(name, isExport),
455                                                           objectExpression,
456                                                           lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
457     auto argument = AllocNode<ir::BinaryExpression>(CreateTsModuleParam(name, isExport),
458                                                     assignExpr,
459                                                     lexer::TokenType::PUNCTUATOR_LOGICAL_OR);
460     if (isExport) {
461         auto *id = AllocNode<ir::Identifier>(name, Allocator());
462         id->AsIdentifier()->SetReference();
463         arguments.push_back(AllocNode<ir::AssignmentExpression>(id, argument,
464             lexer::TokenType::PUNCTUATOR_SUBSTITUTION));
465     } else {
466         arguments.push_back(argument);
467     }
468 
469     auto *callExpr = AllocNode<ir::CallExpression>(funcExpr, std::move(arguments), nullptr, false);
470 
471     return callExpr;
472 }
473 
CreateTsModuleParam(util::StringView paramName,bool isExport)474 ir::Expression *Transformer::CreateTsModuleParam(util::StringView paramName, bool isExport)
475 {
476     if (isExport) {
477         auto moduleName = GetCurrentTSModuleName();
478         auto *id = AllocNode<ir::Identifier>(moduleName, Allocator());
479         id->AsIdentifier()->SetReference();
480         return AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(paramName, Allocator()),
481             ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
482     }
483 
484     auto *id = AllocNode<ir::Identifier>(paramName, Allocator());
485     id->AsIdentifier()->SetReference();
486     return id;
487 }
488 
AddExportLocalEntryItem(util::StringView name,const ir::Identifier * identifier)489 void Transformer::AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier)
490 {
491     auto moduleRecord = GetSourceTextModuleRecord();
492     auto *entry = moduleRecord->NewEntry<SourceTextModuleRecord::ExportEntry>(name, name, identifier, identifier);
493     [[maybe_unused]] bool res = moduleRecord->AddLocalExportEntry(entry);
494     ASSERT(res);
495 }
496 
VisitTsModuleDeclaration(ir::TSModuleDeclaration * node,bool isExport)497 ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *node, bool isExport)
498 {
499     std::vector<ir::AstNode *> res;
500 
501     util::StringView name = GetNameFromModuleDeclaration(node);
502 
503     auto findRes = Scope()->FindLocal(name, binder::ResolveBindingOptions::ALL);
504     if (findRes == nullptr) {
505         bool doExport = isExport && !IsTsModule();
506         auto flag = VariableParsingFlags::VAR;
507         if (IsTsModule()) {
508             flag = VariableParsingFlags::LET;
509         }
510         auto *var = CreateVariableDeclarationWithIdentify(name, flag, node, doExport);
511         if (doExport) {
512             ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
513             res.push_back(AllocNode<ir::ExportNamedDeclaration>(var, std::move(specifiers)));
514             AddExportLocalEntryItem(name, node->Name()->AsIdentifier());
515         } else {
516             res.push_back(var);
517         }
518     }
519 
520     auto *callExpr = CreateCallExpressionForTsModule(node, name, isExport && IsTsModule());
521     auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr);
522     res.push_back(exprStatementNode);
523 
524     return res;
525 }
526 
527 }  // namespace panda::es2panda::parser
528