#include #include template struct Value { using IsExpression = pfor::expr::tag::Expression; T* ptr; Value(T& v): ptr{&v} {} T& eval() { return *ptr; } }; template struct Array { using IsExpression = pfor::expr::tag::Expression; T* ptr; Array(T* v): ptr{v} {} T& operator[](std::size_t i) { return ptr[i]; } }; TEST_CASE("operations") { int a = 240, b = 3; int *pa = &a, *pb = &b; int t[5]{100, 200, 300, 400, 500}, u[5]{1, 2, 3, 4, 5}; int *ps[]{pa, pb}; Value va{a}, vb{b}; Value vpa{pa}, vpb{pb}; Array at{t}, au{u}; Array aps{ps}; int i3{3}; Value v3{i3}; SECTION("unary operators") { SECTION("PostIncr") { int a_{a}, b_{b}, t3{t[3]}; pfor::expr::op::PostIncr o; REQUIRE(o.eval(va) == a_); REQUIRE(a == a_+1); REQUIRE(o.eval(vb) == b_); REQUIRE(b == b_+1); REQUIRE(o.eval(3, at) == t3); REQUIRE(t[3] == t3+1); } SECTION("PostDecr") { int a_{a}, b_{b}, t3{t[3]}; pfor::expr::op::PostDecr o; REQUIRE(o.eval(va) == a_); REQUIRE(a == a_-1); REQUIRE(o.eval(vb) == b_); REQUIRE(b == b_-1); REQUIRE(o.eval(3, at) == t3); REQUIRE(t[3] == t3-1); } SECTION("PreIncr") { int a_{a}, b_{b}, t3{t[3]}; pfor::expr::op::PreIncr o; REQUIRE(o.eval(va) == a_+1); REQUIRE(o.eval(vb) == b_+1); REQUIRE(o.eval(3, at) == t3+1); } SECTION("PreDecr") { int a_{a}, b_{b}, t3{t[3]}; pfor::expr::op::PreDecr o; REQUIRE(o.eval(va) == a_-1); REQUIRE(o.eval(vb) == b_-1); REQUIRE(o.eval(3, at) == t3-1); } SECTION("Plus") { pfor::expr::op::Plus o; REQUIRE(o.eval(va) == a); REQUIRE(o.eval(vb) == b); REQUIRE(o.eval(3, at) == t[3]); } SECTION("Minus") { pfor::expr::op::Minus o; REQUIRE(o.eval(va) == -a); REQUIRE(o.eval(vb) == -b); REQUIRE(o.eval(3, at) == -t[3]); } SECTION("Not") { pfor::expr::op::Not o; REQUIRE_FALSE(o.eval(va)); REQUIRE_FALSE(o.eval(vb)); REQUIRE_FALSE(o.eval(3, at)); } SECTION("BitNot") { pfor::expr::op::BitNot o; REQUIRE(o.eval(va) == ~a); REQUIRE(o.eval(vb) == ~b); REQUIRE(o.eval(3, at) == ~t[3]); } SECTION("Indirection") { pfor::expr::op::Indirection o; REQUIRE(o.eval(vpa) == a); REQUIRE(o.eval(1, aps) == b); } SECTION("AddressOf") { pfor::expr::op::AddressOf o; REQUIRE(o.eval(va) == &a); REQUIRE(o.eval(3, at) == t+3); } } SECTION("binary operators") { SECTION("PtrToMem") { struct Foo { int bar = 42; } foo; Value vm{&Foo::bar}; Value vf{&foo}; decltype(&Foo::bar) const tm[]{&Foo::bar}; Foo*const tf[]{&foo}; Array am{tm}; Array af{tf}; pfor::expr::op::PtrToMem o; // TODO fix segfault in release // REQUIRE(o.eval(vf, vm) == 42); // REQUIRE(o.eval(0, af, am) == 42); } SECTION("Multiplication") { pfor::expr::op::Multiplication o; REQUIRE(o.eval(va, vb) == a*b); REQUIRE(o.eval(3, at, au) == t[3]*u[3]); } SECTION("Division") { pfor::expr::op::Division o; REQUIRE(o.eval(va, vb) == a/b); REQUIRE(o.eval(3, at, au) == t[3]/u[3]); } SECTION("Modulo") { pfor::expr::op::Modulo o; REQUIRE(o.eval(va, vb) == a%b); REQUIRE(o.eval(3, at, au) == t[3]%u[3]); } SECTION("Addition") { pfor::expr::op::Addition o; REQUIRE(o.eval(va, vb) == a+b); REQUIRE(o.eval(3, at, au) == t[3]+u[3]); } SECTION("Subtraction") { pfor::expr::op::Subtraction o; REQUIRE(o.eval(va, vb) == a-b); REQUIRE(o.eval(3, at, au) == t[3]-u[3]); } SECTION("LeftShift") { pfor::expr::op::LeftShift o; REQUIRE(o.eval(va, vb) == a<>b); REQUIRE(o.eval(3, at, au) == t[3]>>u[3]); } SECTION("Lower") { pfor::expr::op::Lower o; REQUIRE(o.eval(va, vb) == ab); REQUIRE(o.eval(3, at, au) == t[3]>u[3]); } SECTION("GreaterEqual") { pfor::expr::op::GreaterEqual o; REQUIRE(o.eval(va, vb) == a>=b); REQUIRE(o.eval(3, at, au) == t[3]>=u[3]); } SECTION("Equal") { pfor::expr::op::Equal o; REQUIRE(o.eval(va, vb) == (a==b)); REQUIRE(o.eval(3, at, au) == (t[3]==u[3])); } SECTION("NotEqual") { pfor::expr::op::NotEqual o; REQUIRE(o.eval(va, vb) == (a!=b)); REQUIRE(o.eval(3, at, au) == (t[3]!=u[3])); } SECTION("BitAnd") { pfor::expr::op::BitAnd o; REQUIRE(o.eval(va, vb) == (a&b)); REQUIRE(o.eval(3, at, au) == (t[3]&u[3])); } SECTION("BitXor") { pfor::expr::op::BitXor o; REQUIRE(o.eval(va, vb) == (a^b)); REQUIRE(o.eval(3, at, au) == (t[3]^u[3])); } SECTION("BitOr") { pfor::expr::op::BitOr o; REQUIRE(o.eval(va, vb) == (a|b)); REQUIRE(o.eval(3, at, au) == (t[3]|u[3])); } SECTION("And") { pfor::expr::op::And o; REQUIRE(o.eval(va, vb) == (a&&b)); REQUIRE(o.eval(3, at, au) == (t[3]&&u[3])); } SECTION("Or") { pfor::expr::op::Or o; REQUIRE(o.eval(va, vb) == (a||b)); REQUIRE(o.eval(3, at, au) == (t[3]||u[3])); } SECTION("Assign") { pfor::expr::op::Assign o; REQUIRE(o.eval(va, vb) == (a=b)); REQUIRE(o.eval(3, at, au) == (t[3]=u[3])); } SECTION("AssignAdd") { pfor::expr::op::AssignAdd o; REQUIRE(o.eval(va, vb) == (a+=b)); REQUIRE(o.eval(3, at, au) == (t[3]+=u[3])); } SECTION("AssignSub") { pfor::expr::op::AssignSub o; REQUIRE(o.eval(va, vb) == (a-=b)); REQUIRE(o.eval(3, at, au) == (t[3]-=u[3])); } SECTION("AssignMul") { pfor::expr::op::AssignMul o; REQUIRE(o.eval(va, vb) == (a*=b)); REQUIRE(o.eval(3, at, au) == (t[3]*=u[3])); } SECTION("AssignDiv") { pfor::expr::op::AssignDiv o; REQUIRE(o.eval(va, vb) == (a/=b)); REQUIRE(o.eval(3, at, au) == (t[3]/=u[3])); } SECTION("AssignMod") { pfor::expr::op::AssignMod o; REQUIRE(o.eval(va, vb) == (a%=b)); REQUIRE(o.eval(3, at, au) == (t[3]%=u[3])); } SECTION("AssignLS") { pfor::expr::op::AssignLS o; REQUIRE(o.eval(va, vb) == (a<<=b)); REQUIRE(o.eval(3, at, au) == (t[3]<<=u[3])); } SECTION("AssignRS") { pfor::expr::op::AssignRS o; REQUIRE(o.eval(va, vb) == (a>>=b)); REQUIRE(o.eval(3, at, au) == (t[3]>>=u[3])); } SECTION("AssignAnd") { pfor::expr::op::AssignAnd o; REQUIRE(o.eval(va, vb) == (a&=b)); REQUIRE(o.eval(3, at, au) == (t[3]&=u[3])); } SECTION("AssignXor") { pfor::expr::op::AssignXor o; REQUIRE(o.eval(va, vb) == (a^=b)); REQUIRE(o.eval(3, at, au) == (t[3]^=u[3])); } SECTION("AssignOr") { pfor::expr::op::AssignOr o; REQUIRE(o.eval(va, vb) == (a|=b)); REQUIRE(o.eval(3, at, au) == (t[3]|=u[3])); } SECTION("Comma") { pfor::expr::op::Comma o; REQUIRE(o.eval(va, vb) == b); REQUIRE(o.eval(3, at, au) == au[3]); REQUIRE(o.eval(va, va, vb) == b); REQUIRE(o.eval(3, at, at, au) == au[3]); } } SECTION("If") { pfor::expr::op::If o; REQUIRE(o.eval(va, va, vb) == a); REQUIRE(o.eval(3, at, at, au) == t[3]); } SECTION("FunctionCall") { auto f1 = []{ return 42; }; auto f2 = [](int i, int j) { return std::to_string(i/2+j); }; decltype(f2) tf2[]{f2}; Array atf2{tf2}; pfor::expr::op::FunctionCall o; REQUIRE(o.eval(Value{f1}) == 42); REQUIRE(o.eval(0, atf2, at, au) == "51"); } SECTION("Subscript") { pfor::expr::op::Subscript o; int i{1}; int id[]{1, 0}; int a[]{3, 2, 1, 0}; int a2[][2]{{3, 2}, {1, 4}}; Value vi{i}; Value va{a}; Array ai{id}; Array aa{a2}; REQUIRE(o.eval(va, vi) == a[i]); REQUIRE(o.eval(1, aa, ai) == a2[1][id[1]]); } }