Skip to content

Commit 15b9ec7

Browse files
authored
Merge pull request #2916 from danpoe/refactor/introduce-imag-and-real-expressions
Introduce complex_imag_exprt and complex_real_exprt
2 parents 4cd1ae5 + 899fe03 commit 15b9ec7

File tree

8 files changed

+210
-62
lines changed

8 files changed

+210
-62
lines changed

src/analyses/goto_rw.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,29 @@ void rw_range_sett::output(std::ostream &out) const
8282
}
8383
}
8484

85-
void rw_range_sett::get_objects_complex(
85+
void rw_range_sett::get_objects_complex_real(
8686
get_modet mode,
87-
const exprt &expr,
87+
const complex_real_exprt &expr,
8888
const range_spect &range_start,
8989
const range_spect &size)
9090
{
91-
const exprt &op=expr.op0();
92-
assert(op.type().id()==ID_complex);
91+
get_objects_rec(mode, expr.op(), range_start, size);
92+
}
9393

94-
range_spect sub_size=
94+
void rw_range_sett::get_objects_complex_imag(
95+
get_modet mode,
96+
const complex_imag_exprt &expr,
97+
const range_spect &range_start,
98+
const range_spect &size)
99+
{
100+
const exprt &op = expr.op();
101+
102+
range_spect sub_size =
95103
to_range_spect(pointer_offset_bits(op.type().subtype(), ns));
96104
assert(sub_size>0);
97-
range_spect offset=
98-
(range_start==-1 || expr.id()==ID_complex_real) ? 0 : sub_size;
105+
range_spect offset = range_start == -1 ? 0 : sub_size;
99106

100-
get_objects_rec(mode, op, range_start+offset, size);
107+
get_objects_rec(mode, op, range_start + offset, size);
101108
}
102109

103110
void rw_range_sett::get_objects_if(
@@ -487,9 +494,12 @@ void rw_range_sett::get_objects_rec(
487494
const range_spect &range_start,
488495
const range_spect &size)
489496
{
490-
if(expr.id()==ID_complex_real ||
491-
expr.id()==ID_complex_imag)
492-
get_objects_complex(mode, expr, range_start, size);
497+
if(expr.id() == ID_complex_real)
498+
get_objects_complex_real(
499+
mode, to_complex_real_expr(expr), range_start, size);
500+
else if(expr.id() == ID_complex_imag)
501+
get_objects_complex_imag(
502+
mode, to_complex_imag_expr(expr), range_start, size);
493503
else if(expr.id()==ID_typecast)
494504
get_objects_typecast(
495505
mode,

src/analyses/goto_rw.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,15 @@ class rw_range_sett
161161
get_modet mode,
162162
const exprt &expr);
163163

164-
virtual void get_objects_complex(
164+
virtual void get_objects_complex_real(
165165
get_modet mode,
166-
const exprt &expr,
166+
const complex_real_exprt &expr,
167+
const range_spect &range_start,
168+
const range_spect &size);
169+
170+
virtual void get_objects_complex_imag(
171+
get_modet mode,
172+
const complex_imag_exprt &expr,
167173
const range_spect &range_start,
168174
const range_spect &size);
169175

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -320,36 +320,80 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
320320
// these should only exist as constants,
321321
// and should already be typed
322322
}
323-
else if(expr.id()==ID_complex_real ||
324-
expr.id()==ID_complex_imag)
323+
else if(expr.id() == ID_complex_real)
325324
{
326-
// get the subtype
327-
assert(expr.operands().size()==1);
328-
const typet &op_type=follow(expr.op0().type());
329-
if(op_type.id()!=ID_complex)
325+
INVARIANT(
326+
expr.operands().size() == 1,
327+
"real part retrieval operation should have one operand");
328+
329+
exprt op = expr.op0();
330+
op.type() = follow(op.type());
331+
332+
if(op.type().id() != ID_complex)
330333
{
331-
if(!is_number(op_type))
334+
if(!is_number(op.type()))
332335
{
333-
err_location(expr.op0());
334-
error() << "real/imag expect numerical operand, "
335-
<< "but got `" << to_string(op_type) << "'" << eom;
336+
err_location(op);
337+
error() << "real part retrieval expects numerical operand, "
338+
<< "but got `" << to_string(op.type()) << "'" << eom;
336339
throw 0;
337340
}
338341

339-
// we could compile away, I suppose
340-
expr.type()=op_type;
341-
expr.op0().make_typecast(complex_typet(op_type));
342+
typecast_exprt typecast_expr(op, complex_typet(op.type()));
343+
complex_real_exprt complex_real_expr(typecast_expr);
344+
345+
expr.swap(complex_real_expr);
342346
}
343347
else
344348
{
345-
expr.type()=op_type.subtype();
349+
complex_real_exprt complex_real_expr(op);
346350

347351
// these are lvalues if the operand is one
348-
if(expr.op0().get_bool(ID_C_lvalue))
349-
expr.set(ID_C_lvalue, true);
352+
if(op.get_bool(ID_C_lvalue))
353+
complex_real_expr.set(ID_C_lvalue, true);
354+
355+
if(op.get_bool(ID_C_constant))
356+
complex_real_expr.set(ID_C_constant, true);
357+
358+
expr.swap(complex_real_expr);
359+
}
360+
}
361+
else if(expr.id() == ID_complex_imag)
362+
{
363+
INVARIANT(
364+
expr.operands().size() == 1,
365+
"imaginary part retrieval operation should have one operand");
366+
367+
exprt op = expr.op0();
368+
op.type() = follow(op.type());
369+
370+
if(op.type().id() != ID_complex)
371+
{
372+
if(!is_number(op.type()))
373+
{
374+
err_location(op);
375+
error() << "real part retrieval expects numerical operand, "
376+
<< "but got `" << to_string(op.type()) << "'" << eom;
377+
throw 0;
378+
}
379+
380+
typecast_exprt typecast_expr(op, complex_typet(op.type()));
381+
complex_imag_exprt complex_imag_expr(typecast_expr);
382+
383+
expr.swap(complex_imag_expr);
384+
}
385+
else
386+
{
387+
complex_imag_exprt complex_imag_expr(op);
388+
389+
// these are lvalues if the operand is one
390+
if(op.get_bool(ID_C_lvalue))
391+
complex_imag_expr.set(ID_C_lvalue, true);
392+
393+
if(op.get_bool(ID_C_constant))
394+
complex_imag_expr.set(ID_C_constant, true);
350395

351-
if(expr.op0().get_bool(ID_C_constant))
352-
expr.set(ID_C_constant, true);
396+
expr.swap(complex_imag_expr);
353397
}
354398
}
355399
else if(expr.id()==ID_generic_selection)

src/goto-symex/symex_assign.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -168,28 +168,29 @@ void goto_symext::symex_assign_rec(
168168
symex_assign_byte_extract(
169169
state, to_byte_extract_expr(lhs), full_lhs, rhs, guard, assignment_type);
170170
}
171-
else if(lhs.id()==ID_complex_real ||
172-
lhs.id()==ID_complex_imag)
171+
else if(lhs.id() == ID_complex_real)
173172
{
174-
// this is stuff like __real__ x = 1;
175-
assert(lhs.operands().size()==1);
173+
const complex_real_exprt &complex_real_expr = to_complex_real_expr(lhs);
176174

177-
exprt new_rhs=exprt(ID_complex, lhs.op0().type());
178-
new_rhs.operands().resize(2);
175+
const complex_imag_exprt complex_imag_expr(complex_real_expr.op());
179176

180-
if(lhs.id()==ID_complex_real)
181-
{
182-
new_rhs.op0()=rhs;
183-
new_rhs.op1()=unary_exprt(ID_complex_imag, lhs.op0(), lhs.type());
184-
}
185-
else
186-
{
187-
new_rhs.op0()=unary_exprt(ID_complex_real, lhs.op0(), lhs.type());
188-
new_rhs.op1()=rhs;
189-
}
177+
complex_exprt new_rhs(
178+
rhs, complex_imag_expr, to_complex_type(complex_real_expr.op().type()));
179+
180+
symex_assign_rec(
181+
state, complex_real_expr.op(), full_lhs, new_rhs, guard, assignment_type);
182+
}
183+
else if(lhs.id() == ID_complex_imag)
184+
{
185+
const complex_imag_exprt &complex_imag_expr = to_complex_imag_expr(lhs);
186+
187+
const complex_real_exprt complex_real_expr(complex_imag_expr.op());
188+
189+
complex_exprt new_rhs(
190+
complex_real_expr, rhs, to_complex_type(complex_imag_expr.op().type()));
190191

191192
symex_assign_rec(
192-
state, lhs.op0(), full_lhs, new_rhs, guard, assignment_type);
193+
state, complex_imag_expr.op(), full_lhs, new_rhs, guard, assignment_type);
193194
}
194195
else
195196
throw "assignment to `"+lhs.id_string()+"' not handled";

src/solvers/flattening/boolbv.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
278278
else if(expr.id()==ID_complex)
279279
return convert_complex(expr);
280280
else if(expr.id()==ID_complex_real)
281-
return convert_complex_real(expr);
281+
return convert_complex_real(to_complex_real_expr(expr));
282282
else if(expr.id()==ID_complex_imag)
283-
return convert_complex_imag(expr);
283+
return convert_complex_imag(to_complex_imag_expr(expr));
284284
else if(expr.id()==ID_lambda)
285285
return convert_lambda(expr);
286286
else if(expr.id()==ID_array_of)

src/solvers/flattening/boolbv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ class boolbvt:public arrayst
142142
virtual bvt convert_array(const exprt &expr);
143143
virtual bvt convert_vector(const exprt &expr);
144144
virtual bvt convert_complex(const exprt &expr);
145-
virtual bvt convert_complex_real(const exprt &expr);
146-
virtual bvt convert_complex_imag(const exprt &expr);
145+
virtual bvt convert_complex_real(const complex_real_exprt &expr);
146+
virtual bvt convert_complex_imag(const complex_imag_exprt &expr);
147147
virtual bvt convert_lambda(const exprt &expr);
148148
virtual bvt convert_let(const let_exprt &);
149149
virtual bvt convert_array_of(const array_of_exprt &expr);

src/solvers/flattening/boolbv_complex.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,35 +45,29 @@ bvt boolbvt::convert_complex(const exprt &expr)
4545
return conversion_failed(expr);
4646
}
4747

48-
bvt boolbvt::convert_complex_real(const exprt &expr)
48+
bvt boolbvt::convert_complex_real(const complex_real_exprt &expr)
4949
{
5050
std::size_t width=boolbv_width(expr.type());
5151

5252
if(width==0)
5353
return conversion_failed(expr);
5454

55-
if(expr.operands().size()!=1)
56-
return conversion_failed(expr);
57-
58-
bvt bv=convert_bv(expr.op0());
55+
bvt bv = convert_bv(expr.op());
5956

6057
assert(bv.size()==width*2);
6158
bv.resize(width); // chop
6259

6360
return bv;
6461
}
6562

66-
bvt boolbvt::convert_complex_imag(const exprt &expr)
63+
bvt boolbvt::convert_complex_imag(const complex_imag_exprt &expr)
6764
{
6865
std::size_t width=boolbv_width(expr.type());
6966

7067
if(width==0)
7168
return conversion_failed(expr);
7269

73-
if(expr.operands().size()!=1)
74-
return conversion_failed(expr);
75-
76-
bvt bv=convert_bv(expr.op0());
70+
bvt bv = convert_bv(expr.op());
7771

7872
assert(bv.size()==width*2);
7973
bv.erase(bv.begin(), bv.begin()+width);

src/util/std_expr.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,99 @@ inline void validate_expr(const complex_exprt &value)
17731773
validate_operands(value, 2, "Complex constructor must have two operands");
17741774
}
17751775

1776+
/// \brief Real part of the expression describing a complex number.
1777+
class complex_real_exprt : public unary_exprt
1778+
{
1779+
public:
1780+
explicit complex_real_exprt(const exprt &op)
1781+
: unary_exprt(ID_complex_real, op, to_complex_type(op.type()).subtype())
1782+
{
1783+
}
1784+
};
1785+
1786+
/// \brief Cast an exprt to a \ref complex_real_exprt
1787+
///
1788+
/// \a expr must be known to be a \ref complex_real_exprt.
1789+
///
1790+
/// \param expr: Source expression
1791+
/// \return Object of type \ref complex_real_exprt
1792+
inline const complex_real_exprt &to_complex_real_expr(const exprt &expr)
1793+
{
1794+
PRECONDITION(expr.id() == ID_complex_real);
1795+
DATA_INVARIANT(
1796+
expr.operands().size() == 1,
1797+
"real part retrieval operation must have one operand");
1798+
return static_cast<const complex_real_exprt &>(expr);
1799+
}
1800+
1801+
/// \copydoc to_complex_real_expr(const exprt &)
1802+
inline complex_real_exprt &to_complex_real_expr(exprt &expr)
1803+
{
1804+
PRECONDITION(expr.id() == ID_complex_real);
1805+
DATA_INVARIANT(
1806+
expr.operands().size() == 1,
1807+
"real part retrieval operation must have one operand");
1808+
return static_cast<complex_real_exprt &>(expr);
1809+
}
1810+
1811+
template <>
1812+
inline bool can_cast_expr<complex_real_exprt>(const exprt &base)
1813+
{
1814+
return base.id() == ID_complex_real;
1815+
}
1816+
1817+
inline void validate_expr(const complex_real_exprt &expr)
1818+
{
1819+
validate_operands(
1820+
expr, 1, "real part retrieval operation must have one operand");
1821+
}
1822+
1823+
/// \brief Imaginary part of the expression describing a complex number.
1824+
class complex_imag_exprt : public unary_exprt
1825+
{
1826+
public:
1827+
explicit complex_imag_exprt(const exprt &op)
1828+
: unary_exprt(ID_complex_imag, op, to_complex_type(op.type()).subtype())
1829+
{
1830+
}
1831+
};
1832+
1833+
/// \brief Cast an exprt to a \ref complex_imag_exprt
1834+
///
1835+
/// \a expr must be known to be a \ref complex_imag_exprt.
1836+
///
1837+
/// \param expr: Source expression
1838+
/// \return Object of type \ref complex_imag_exprt
1839+
inline const complex_imag_exprt &to_complex_imag_expr(const exprt &expr)
1840+
{
1841+
PRECONDITION(expr.id() == ID_complex_imag);
1842+
DATA_INVARIANT(
1843+
expr.operands().size() == 1,
1844+
"imaginary part retrieval operation must have one operand");
1845+
return static_cast<const complex_imag_exprt &>(expr);
1846+
}
1847+
1848+
/// \copydoc to_complex_imag_expr(const exprt &)
1849+
inline complex_imag_exprt &to_complex_imag_expr(exprt &expr)
1850+
{
1851+
PRECONDITION(expr.id() == ID_complex_imag);
1852+
DATA_INVARIANT(
1853+
expr.operands().size() == 1,
1854+
"imaginary part retrieval operation must have one operand");
1855+
return static_cast<complex_imag_exprt &>(expr);
1856+
}
1857+
1858+
template <>
1859+
inline bool can_cast_expr<complex_imag_exprt>(const exprt &base)
1860+
{
1861+
return base.id() == ID_complex_imag;
1862+
}
1863+
1864+
inline void validate_expr(const complex_imag_exprt &expr)
1865+
{
1866+
validate_operands(
1867+
expr, 1, "imaginary part retrieval operation must have one operand");
1868+
}
17761869

17771870
class namespacet;
17781871

0 commit comments

Comments
 (0)