From 15facd4403b05eed8a501a081dee52f073b1ebd8 Mon Sep 17 00:00:00 2001 From: Andy Fingerhut Date: Sun, 27 Aug 2023 12:41:55 -0400 Subject: [PATCH 1/2] Language grammar changes to add for loop --- frontends/parsers/p4/p4parser.ypp | 72 +++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index 3cbceea7897..05dec8156b0 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -228,7 +228,7 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %token RANGE ".." %token TRUE FALSE THIS %token ABSTRACT ACTION ACTIONS APPLY BOOL BIT CONST CONTROL DEFAULT - ELSE ENTRIES ENUM ERROR EXIT EXTERN HEADER HEADER_UNION IF IN INOUT + ELSE ENTRIES ENUM ERROR EXIT EXTERN FOR HEADER HEADER_UNION IF IN INOUT INT KEY LIST SELECT MATCH_KIND TYPE OUT PACKAGE PARSER PRAGMA PRIORITY RETURN STATE STRING STRUCT SWITCH TABLE TRANSITION TUPLE TYPEDEF VARBIT VALUESET VOID @@ -270,7 +270,9 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %type statement emptyStatement returnStatement switchStatement exitStatement assignmentOrMethodCallStatement conditionalStatement + assignmentOrMethodCallStatementWithoutSemicolon directApplication + forStatement %type blockStatement parserBlockStatement controlBody objInitializer %type statementOrDeclaration parserStatement @@ -282,7 +284,7 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %type parserState %type*> parserStates %type constantDeclaration actionDeclaration - variableDeclaration instantiation functionDeclaration + variableDeclaration variableDeclarationWithoutSemicolon instantiation functionDeclaration objDeclaration tableDeclaration controlLocalDeclaration parserLocalElement valueSetDeclaration %type headerTypeDeclaration structTypeDeclaration @@ -1180,18 +1182,22 @@ typedefDeclaration /*************************** STATEMENTS *************************/ assignmentOrMethodCallStatement + : assignmentOrMethodCallStatementWithoutSemicolon ";" { $$ = $1; } + ; + +assignmentOrMethodCallStatementWithoutSemicolon // These rules are overly permissive, but they avoid some conflicts - : lvalue "(" argumentList ")" ";" + : lvalue "(" argumentList ")" { auto mc = new IR::MethodCallExpression(@1 + @4, $1, new IR::Vector(), $3); $$ = new IR::MethodCallStatement(@1 + @4, mc); } - | lvalue l_angle typeArgumentList r_angle "(" argumentList ")" ";" + | lvalue l_angle typeArgumentList r_angle "(" argumentList ")" { auto mc = new IR::MethodCallExpression(@1 + @7, $1, $3, $6); $$ = new IR::MethodCallStatement(@1 + @7, mc); } - | lvalue "=" expression ";" + | lvalue "=" expression { $$ = new IR::AssignmentStatement(@2, $1, $3); } ; @@ -1239,6 +1245,7 @@ statement | returnStatement { $$ = $1; } | exitStatement { $$ = $1; } | switchStatement { $$ = $1; } + | forStatement { $$ = $1; } ; blockStatement @@ -1279,6 +1286,49 @@ statementOrDeclaration | instantiation { $$ = $1; } ; +forStatement + : FOR "(" forInitStatements ";" + expression ";" + forUpdateStatements ")" + statement + { $$ = $9; } // TODO: temporary placeholder code to avoid bison warning + | FOR "(" typeRef name IN forCollectionExpr ")" + statement + { $$ = $8; } // TODO: temporary placeholder code to avoid bison warning + ; + +forInitStatements + : %empty + | forInitStatementsNonEmpty + ; + +forInitStatementsNonEmpty + : declOrAssignmentOrMethodCallStatement + | declOrAssignmentOrMethodCallStatement "," forInitStatementsNonEmpty + ; + +declOrAssignmentOrMethodCallStatement + : variableDeclarationWithoutSemicolon + | assignmentOrMethodCallStatementWithoutSemicolon + ; + +forUpdateStatements + : %empty + | forUpdateStatementsNonEmpty + ; + +forUpdateStatementsNonEmpty + : assignmentOrMethodCallStatementWithoutSemicolon + | assignmentOrMethodCallStatementWithoutSemicolon "," + forUpdateStatementsNonEmpty + ; + +forCollectionExpr + : expression + | expression ".." expression + | typeRef + ; + /************************* TABLE *********************************/ tableDeclaration @@ -1382,12 +1432,16 @@ actionDeclaration /************************* VARIABLES *****************************/ variableDeclaration - : annotations typeRef name optInitializer ";" + : variableDeclarationWithoutSemicolon ";" { $$ = $1; } + ; + +variableDeclarationWithoutSemicolon + : annotations typeRef name optInitializer { auto ann = new IR::Annotations(@1, *$1); - $$ = new IR::Declaration_Variable(@1+@4, *$3, ann, $2, $4); + $$ = new IR::Declaration_Variable(@1, *$3, ann, $2, $4); driver.structure->declareObject(*$3, $2->toString()); } - | typeRef name optInitializer ";" - { $$ = new IR::Declaration_Variable(@1+@4, *$2, $1, $3); + | typeRef name optInitializer + { $$ = new IR::Declaration_Variable(@1, *$2, $1, $3); driver.structure->declareObject(*$2, $1->toString()); } ; From 4b8dedc1f9364ab7f7deb6bde56d6a42d007e315 Mon Sep 17 00:00:00 2001 From: Chris Dodd Date: Mon, 25 Mar 2024 16:54:50 +1300 Subject: [PATCH 2/2] IR classes for For and ForInStatements --- frontends/parsers/p4/p4parser.ypp | 42 +++++++++++++++++-------------- ir/dbprint-stmt.cpp | 23 +++++++++++++++++ ir/ir.def | 22 ++++++++++++++++ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index f861dde8075..fe38c26b5d4 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -247,7 +247,7 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { stateExpression optInitializer initializer simpleKeysetExpression transitionStatement switchLabel p4rtControllerType reducedSimpleKeysetExpression entryPriority - nonBraceExpression + nonBraceExpression forCollectionExpr %type baseType typeOrVoid specializedType headerStackType typeRef tupleType typeArg realTypeArg namedType p4listType %type typeName @@ -276,8 +276,10 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %type blockStatement parserBlockStatement controlBody objInitializer %type statementOrDeclaration parserStatement -%type*> objDeclarations statOrDeclList - parserStatements + declOrAssignmentOrMethodCallStatement +%type*> objDeclarations statOrDeclList parserStatements + forInitStatements forInitStatementsNonEmpty + forUpdateStatements forUpdateStatementsNonEmpty %type switchCase %type*> switchCases %type*> typeArgumentList realTypeArgumentList @@ -1295,42 +1297,44 @@ forStatement expression ";" forUpdateStatements ")" statement - { $$ = $9; } // TODO: temporary placeholder code to avoid bison warning + { $$ = new IR::ForStatement(@1+@8, *$3, $5, *$7, $9); } | FOR "(" typeRef name IN forCollectionExpr ")" statement - { $$ = $8; } // TODO: temporary placeholder code to avoid bison warning + { $$ = new IR::ForInStatement(@1+@6, new IR::Declaration_Variable(@3+@4, *$4, $3), $6, $8); } ; forInitStatements - : %empty - | forInitStatementsNonEmpty + : %empty { $$ = new IR::IndexedVector(); } + | forInitStatementsNonEmpty { $$ = $1; } ; forInitStatementsNonEmpty - : declOrAssignmentOrMethodCallStatement - | declOrAssignmentOrMethodCallStatement "," forInitStatementsNonEmpty + : declOrAssignmentOrMethodCallStatement { $$ = new IR::IndexedVector($1); } + | forInitStatementsNonEmpty "," declOrAssignmentOrMethodCallStatement { + ($$ = $1)->push_back($3); } ; declOrAssignmentOrMethodCallStatement - : variableDeclarationWithoutSemicolon - | assignmentOrMethodCallStatementWithoutSemicolon + : variableDeclarationWithoutSemicolon { $$ = $1; } + | assignmentOrMethodCallStatementWithoutSemicolon { $$ = $1; } ; forUpdateStatements - : %empty - | forUpdateStatementsNonEmpty + : %empty { $$ = new IR::IndexedVector(); } + | forUpdateStatementsNonEmpty { $$ = $1; } ; forUpdateStatementsNonEmpty - : assignmentOrMethodCallStatementWithoutSemicolon - | assignmentOrMethodCallStatementWithoutSemicolon "," - forUpdateStatementsNonEmpty + : assignmentOrMethodCallStatementWithoutSemicolon { + $$ = new IR::IndexedVector($1); } + | forUpdateStatementsNonEmpty "," assignmentOrMethodCallStatementWithoutSemicolon { + ($$ = $1)->push_back($3); } ; forCollectionExpr - : expression - | expression ".." expression - | typeRef + : expression { $$ = $1; } + | expression ".." expression { $$ = new IR::Range(@1 + @3, $1, $3); } + | typeRef { $$ = new IR::ConstructorCallExpression(@1, $1, {}); } ; /************************* TABLE *********************************/ diff --git a/ir/dbprint-stmt.cpp b/ir/dbprint-stmt.cpp index 5047e7faac9..d0ade984ed2 100644 --- a/ir/dbprint-stmt.cpp +++ b/ir/dbprint-stmt.cpp @@ -87,3 +87,26 @@ void IR::SwitchStatement::dbprint(std::ostream &out) const { } out << unindent << " }" << setprec(prec); } + +void IR::ForStatement::dbprint(std::ostream &out) const { + int prec = getprec(out); + out << Prec_Low << "for ("; + bool first = true; + for (auto *sd : init) { + if (!first) out << ", "; + out << sd; + first = false; } + out << "; " << condition << "; "; + first = true; + for (auto *sd : updates) { + if (!first) out << ", "; + out << sd; + first = false; } + out << "{" << indent << Log::endl << body << " }" << unindent << setprec(prec); +} + +void IR::ForInStatement::dbprint(std::ostream &out) const { + int prec = getprec(out); + out << Prec_Low << "for (" << decl << " in " << collection << ") {" << indent + << Log::endl << body << " }" << unindent << setprec(prec); +} diff --git a/ir/ir.def b/ir/ir.def index 3ea69913038..523deac8913 100644 --- a/ir/ir.def +++ b/ir/ir.def @@ -504,6 +504,28 @@ class SwitchStatement : Statement { split.run_visit(); } } +class ForStatement : Statement { + inline IndexedVector init; + Expression condition; + inline IndexedVector updates; + Statement body; + visit_children { + v.visit(init, "init"); + v.visit(condition, "condition"); + // FIXME -- need visit closure over the body and updates + condition + v.visit(body, "body"); + v.visit(updates, "updates"); } +} + +// FIXME -- should we try to directly convert this to a ForStatement in the parser? +class ForInStatement : Statement { + Declaration_Variable decl; + Expression collection; + Statement body; +} + +///////////////////////////////////////////////////////////// + class Function : Declaration, IFunctional, ISimpleNamespace, INestedNamespace { Type_Method type; BlockStatement body;