@@ -3156,6 +3156,31 @@ absl::StatusOr<Function*> Parser::ParseProcConfig(
31563156 return config;
31573157}
31583158
3159+ absl::StatusOr<Function*> Parser::ParseProcNextExplicitStateAccess (
3160+ std::vector<Param*> next_params, std::string_view proc_name,
3161+ std::vector<ParametricBinding*> parametric_bindings, Token oparen,
3162+ Bindings& inner_bindings, bool is_public) {
3163+ for (Param* p : next_params) {
3164+ if (HasChannelElement (p->type_annotation ())) {
3165+ return ParseErrorStatus (p->span (),
3166+ " Channels cannot be Proc next params." );
3167+ }
3168+ }
3169+ TypeAnnotation* return_type = module_->Make <TupleTypeAnnotation>(
3170+ Span (GetPos (), GetPos ()), std::vector<TypeAnnotation*>{});
3171+ XLS_ASSIGN_OR_RETURN (StatementBlock * body,
3172+ ParseBlockExpression (inner_bindings));
3173+ Span span (oparen.span ().start (), GetPos ());
3174+ NameDef* name_def =
3175+ module_->Make <NameDef>(span, absl::StrCat (proc_name, " .next" ), nullptr );
3176+ Function* next = module_->Make <Function>(
3177+ span, name_def, std::move (parametric_bindings), next_params, return_type,
3178+ body, FunctionTag::kProcNext , is_public,
3179+ /* is_stub=*/ false );
3180+ name_def->set_definer (next);
3181+ return next;
3182+ }
3183+
31593184absl::StatusOr<Function*> Parser::ParseProcNext (
31603185 Bindings& bindings, std::vector<ParametricBinding*> parametric_bindings,
31613186 std::string_view proc_name, bool is_public) {
@@ -3176,7 +3201,11 @@ absl::StatusOr<Function*> Parser::ParseProcNext(
31763201
31773202 XLS_ASSIGN_OR_RETURN (std::vector<Param*> next_params,
31783203 ParseCommaSeq<Param*>(parse_param, TokenKind::kCParen ));
3179-
3204+ if (module_->attributes ().contains (ModuleAttribute::kExplicitStateAccess )) {
3205+ return ParseProcNextExplicitStateAccess (next_params, proc_name,
3206+ parametric_bindings, oparen,
3207+ inner_bindings, is_public);
3208+ }
31803209 if (next_params.size () != 1 ) {
31813210 std::string next_params_str =
31823211 absl::StrJoin (next_params, " , " , [](std::string* out, const Param* p) {
@@ -3195,15 +3224,9 @@ absl::StatusOr<Function*> Parser::ParseProcNext(
31953224 " Channels cannot be Proc next params." );
31963225 }
31973226
3198- TypeAnnotation* return_type;
3199- if (module_->attributes ().contains (ModuleAttribute::kExplicitStateAccess )) {
3200- return_type = module_->Make <TupleTypeAnnotation>(
3201- state_param->span (), std::vector<TypeAnnotation*>{});
3202- } else {
3203- XLS_ASSIGN_OR_RETURN (return_type,
3204- CloneNode (state_param->type_annotation (),
3205- &PreserveTypeDefinitionsReplacer));
3206- }
3227+ XLS_ASSIGN_OR_RETURN (TypeAnnotation * return_type,
3228+ CloneNode (state_param->type_annotation (),
3229+ &PreserveTypeDefinitionsReplacer));
32073230 XLS_ASSIGN_OR_RETURN (StatementBlock * body,
32083231 ParseBlockExpression (inner_bindings));
32093232 Span span (oparen.span ().start (), GetPos ());
@@ -3522,12 +3545,34 @@ absl::StatusOr<ModuleMember> Parser::ParseProcLike(const Pos& start_pos,
35223545
35233546 // Just as with proc member decls, we need the init fn to have its own return
35243547 // type, to avoid parent/child relationship violations.
3525- XLS_ASSIGN_OR_RETURN (auto * init_return_type,
3526- CloneNode (proc_like_body.next ->return_type (),
3527- &PreserveTypeDefinitionsReplacer));
3548+ TypeAnnotation* type_to_clone;
3549+ if (module_->attributes ().contains (ModuleAttribute::kExplicitStateAccess )) {
3550+ if (proc_like_body.next ->params ().empty ()) {
3551+ type_to_clone = proc_like_body.next ->return_type ();
3552+ } else if (proc_like_body.next ->params ().size () == 1 ) {
3553+ type_to_clone = proc_like_body.next ->params ()[0 ]->type_annotation ();
3554+ } else {
3555+ std::vector<TypeAnnotation*> member_types;
3556+ member_types.reserve (proc_like_body.next ->params ().size ());
3557+ for (Param* param : proc_like_body.next ->params ()) {
3558+ XLS_ASSIGN_OR_RETURN (TypeAnnotation * cloned_type,
3559+ CloneNode (param->type_annotation (),
3560+ &PreserveTypeDefinitionsReplacer));
3561+ member_types.push_back (cloned_type);
3562+ }
3563+ Span span (proc_like_body.next ->params ().front ()->span ().start (),
3564+ proc_like_body.next ->params ().back ()->span ().limit ());
3565+ type_to_clone = module_->Make <TupleTypeAnnotation>(span, member_types);
3566+ }
3567+ } else {
3568+ type_to_clone = proc_like_body.next ->return_type ();
3569+ }
3570+
3571+ XLS_ASSIGN_OR_RETURN (
3572+ TypeAnnotation * init_return_type,
3573+ CloneNode (type_to_clone, &PreserveTypeDefinitionsReplacer));
35283574 init_return_type->SetParentage ();
3529- proc_like_body.init ->set_return_type (
3530- down_cast<TypeAnnotation*>(init_return_type));
3575+ proc_like_body.init ->set_return_type (init_return_type);
35313576 proc_like_body.init ->SetParentage ();
35323577
35333578 auto * proc_like = module_->Make <T>(span, body_span, name_def,
0 commit comments