Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions tools/sddl2/compiler/semantic_analyzer/SemanticAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,27 @@ class SemanticAnalyzerImpl {
return Type{ TypeKind::NONE };
}

std::optional<Type> findField(const ASTVec& fields, const std::string& name)
{
for (const auto& field : fields) {
if (auto record_field = field->as_record_field()) {
auto& field_name = record_field->name()->as_var()->name();
if (field_name == name) {
return assumedType(analyzeNode(record_field->type()));
}
}
if (auto when = field->as_when()) {
auto found_type = findField(when->body(), name);
if (found_type) {
throw SemanticError(
field->loc(),
"Member access not supported on optional fields.");
}
}
}
return std::nullopt;
}

Type analyzeMember(const ASTOp& op)
{
auto saved_vars = var_types_;
Expand All @@ -319,14 +340,7 @@ class SemanticAnalyzerImpl {
}

// Find the field
std::optional<Type> found_type;
for (const auto& field : record->fields()) {
auto record_field = field->as_record_field();
auto& name = record_field->name()->as_var()->name();
if (name == field_name) {
found_type = assumedType(analyzeNode(record_field->type()));
}
}
auto found_type = findField(record->fields(), field_name);
if (!found_type) {
throw SemanticError(
op.args()[1]->loc(),
Expand Down
31 changes: 31 additions & 0 deletions tools/sddl2/compiler/tests/SemanticAnalyzerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,35 @@ TEST_F(SemanticAnalyzerTest, WhenBlockInRecordWithFieldReference)
expect_error(prog, "Undefined variable");
}

TEST_F(SemanticAnalyzerTest, MemberAccessOnConditionalField)
{
const auto prog = R"(
Record Data(flags) = {
when flags {
optional: Int32LE
}
}
data: Data(1)
expect data.optional == 0
)";
expect_error(prog, "access not supported");
}

TEST_F(SemanticAnalyzerTest, MemberAccessOnNonConditionalField)
{
const auto prog = R"(
Record Data(flags) = {
when flags {
optional: Int32LE
},
present: Int32LE
}
data: Data(1)
expect data.present == 0
)";

// TODO: this will pass once codegen is implemented
expect_error(prog, "code generation error");
}

} // namespace openzl::sddl2::tests
Loading