Skip to content
Merged
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
98 changes: 98 additions & 0 deletions src/verilog/verilog_typecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,104 @@ void verilog_typecheckt::assignment_conversion(
exprt &rhs,
const typet &lhs_type)
{
// 1800-2017 10.9
if(rhs.type().id() == ID_verilog_assignment_pattern)
{
DATA_INVARIANT(
rhs.id() == ID_verilog_assignment_pattern,
"verilog_assignment_pattern expression expected");
if(lhs_type.id() == ID_struct)
{
auto &struct_type = to_struct_type(lhs_type);
auto &components = struct_type.components();

if(
!rhs.operands().empty() &&
rhs.operands().front().id() == ID_member_initializer)
{
exprt::operandst initializers{components.size(), nil_exprt{}};

for(auto &op : rhs.operands())
{
PRECONDITION(op.id() == ID_member_initializer);
auto member_name = op.get(ID_member_name);
if(!struct_type.has_component(member_name))
{
throw errort().with_location(op.source_location())
<< "struct does not have a member `" << member_name << "'";
}
auto nr = struct_type.component_number(member_name);
auto value = to_unary_expr(op).op();
// rec. call
assignment_conversion(value, components[nr].type());
initializers[nr] = std::move(value);
}

// Is every member covered?
for(std::size_t i = 0; i < components.size(); i++)
if(initializers[i].is_nil())
{
throw errort().with_location(rhs.source_location())
<< "assignment pattern does not assign member `"
<< components[i].get_name() << "'";
}

rhs = struct_exprt{std::move(initializers), struct_type}
.with_source_location(rhs.source_location());
}
else
{
if(rhs.operands().size() != components.size())
{
throw errort().with_location(rhs.source_location())
<< "number of expressions does not match number of struct members";
}

for(std::size_t i = 0; i < components.size(); i++)
{
// rec. call
assignment_conversion(rhs.operands()[i], components[i].type());
}

// turn into struct expression
rhs.id(ID_struct);
rhs.type() = lhs_type;
}

return;
}
else if(lhs_type.id() == ID_array)
{
auto &array_type = to_array_type(lhs_type);
auto &element_type = array_type.element_type();
auto array_size =
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));

if(array_size != rhs.operands().size())
{
throw errort().with_location(rhs.source_location())
<< "number of expressions does not match number of array elements";
}

for(std::size_t i = 0; i < array_size; i++)
{
// rec. call
assignment_conversion(rhs.operands()[i], element_type);
}

// turn into array expression
rhs.id(ID_array);
rhs.type() = lhs_type;
return;
}
else
{
throw errort().with_location(rhs.source_location())
<< "cannot convert assignment pattern to '" << to_string(lhs_type)
<< '\'';
}
}

// Implements 1800-2017 10.7
// If the RHS is smaller than the LHS:
// * if the RHS is unsigned, it is zero-padded
Expand Down
96 changes: 0 additions & 96 deletions src/verilog/verilog_typecheck_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2191,102 +2191,6 @@ void verilog_typecheck_exprt::implicit_typecast(
return;
}
}
else if(src_type.id() == ID_verilog_assignment_pattern)
{
DATA_INVARIANT(
expr.id() == ID_verilog_assignment_pattern,
"verilog_assignment_pattern expression expected");
if(dest_type.id() == ID_struct)
{
auto &struct_type = to_struct_type(dest_type);
auto &components = struct_type.components();

if(
!expr.operands().empty() &&
expr.operands().front().id() == ID_member_initializer)
{
exprt::operandst initializers{components.size(), nil_exprt{}};

for(auto &op : expr.operands())
{
PRECONDITION(op.id() == ID_member_initializer);
auto member_name = op.get(ID_member_name);
if(!struct_type.has_component(member_name))
{
throw errort().with_location(op.source_location())
<< "struct does not have a member `" << member_name << "'";
}
auto nr = struct_type.component_number(member_name);
auto value = to_unary_expr(op).op();
// rec. call
implicit_typecast(value, components[nr].type());
initializers[nr] = std::move(value);
}

// Is every member covered?
for(std::size_t i = 0; i < components.size(); i++)
if(initializers[i].is_nil())
{
throw errort().with_location(expr.source_location())
<< "assignment pattern does not assign member `"
<< components[i].get_name() << "'";
}

expr = struct_exprt{std::move(initializers), struct_type}
.with_source_location(expr.source_location());
}
else
{
if(expr.operands().size() != components.size())
{
throw errort().with_location(expr.source_location())
<< "number of expressions does not match number of struct members";
}

for(std::size_t i = 0; i < components.size(); i++)
{
// rec. call
implicit_typecast(expr.operands()[i], components[i].type());
}

// turn into struct expression
expr.id(ID_struct);
expr.type() = dest_type;
}

return;
}
else if(dest_type.id() == ID_array)
{
auto &array_type = to_array_type(dest_type);
auto &element_type = array_type.element_type();
auto array_size =
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));

if(array_size != expr.operands().size())
{
throw errort().with_location(expr.source_location())
<< "number of expressions does not match number of array elements";
}

for(std::size_t i = 0; i < array_size; i++)
{
// rec. call
implicit_typecast(expr.operands()[i], element_type);
}

// turn into array expression
expr.id(ID_array);
expr.type() = dest_type;
return;
}
else
{
throw errort().with_location(expr.source_location())
<< "cannot convert assignment pattern to '" << to_string(dest_type)
<< '\'';
}
}
else if(src_type.id() == ID_verilog_real)
{
if(
Expand Down
Loading