Skip to content

Commit 8a26641

Browse files
NL02copybara-github
authored andcommitted
[Explicit State Access] Return the type as the initialized state in init
Currently it returns the same type as Proc Next field which is an empty tuple. PiperOrigin-RevId: 862298516
1 parent b736a51 commit 8a26641

File tree

3 files changed

+105
-16
lines changed

3 files changed

+105
-16
lines changed

xls/dslx/frontend/parser.cc

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
31593184
absl::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,

xls/dslx/frontend/parser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,10 @@ class Parser : public TokenParser {
704704
Bindings& bindings, std::vector<ParametricBinding*> parametric_bindings,
705705
const std::vector<ProcMember*>& proc_members, std::string_view proc_name,
706706
bool is_public);
707-
707+
absl::StatusOr<Function*> ParseProcNextExplicitStateAccess(
708+
std::vector<Param*> next_params, std::string_view proc_name,
709+
std::vector<ParametricBinding*> parametric_bindings, Token oparen,
710+
Bindings& inner_bindings, bool is_public);
708711
absl::StatusOr<Function*> ParseProcNext(
709712
Bindings& bindings, std::vector<ParametricBinding*> parametric_bindings,
710713
std::string_view proc_name, bool is_public);

xls/dslx/frontend/parser_test.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,6 +3495,47 @@ proc simple {
34953495
EXPECT_EQ(next.return_type()->ToString(), "()");
34963496
}
34973497

3498+
TEST_F(ParserTest, ExplicitStateAccessProcInitReturnsSameTypeAsSelf) {
3499+
constexpr std::string_view kProgram = R"(#![feature(explicit_state_access)]
3500+
proc simple {
3501+
config() {
3502+
()
3503+
}
3504+
init {
3505+
u32:0
3506+
}
3507+
next(state: u32) {
3508+
}
3509+
})";
3510+
XLS_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Module> module, Parse(kProgram));
3511+
XLS_ASSERT_OK_AND_ASSIGN(Proc * proc,
3512+
module->GetMemberOrError<Proc>("simple"));
3513+
const Function& init = proc->init();
3514+
ASSERT_NE(init.return_type(), nullptr);
3515+
EXPECT_EQ(init.return_type()->ToString(), "u32");
3516+
}
3517+
3518+
TEST_F(ParserTest,
3519+
ExplicitStateAccessProcInitMultipleStatesReturnsSameTypeAsSelf) {
3520+
constexpr std::string_view kProgram = R"(#![feature(explicit_state_access)]
3521+
proc simple {
3522+
config() {
3523+
()
3524+
}
3525+
init {
3526+
((u32:0, u32:1), u32:0)
3527+
}
3528+
next(state1: (u32, u32), state2: u32) {
3529+
}
3530+
})";
3531+
XLS_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Module> module, Parse(kProgram));
3532+
XLS_ASSERT_OK_AND_ASSIGN(Proc * proc,
3533+
module->GetMemberOrError<Proc>("simple"));
3534+
const Function& init = proc->init();
3535+
ASSERT_NE(init.return_type(), nullptr);
3536+
EXPECT_EQ(init.return_type()->ToString(), "((u32, u32), u32)");
3537+
}
3538+
34983539
// Verifies that we can walk backwards through a tree. In this case, from the
34993540
// terminal node to the defining expr.
35003541
TEST(ParserBackrefTest, CanFindDefiner) {

0 commit comments

Comments
 (0)