forked from OSchip/llvm-project
[flang] Remove GenericExpr, move operator overloads to tools.h
Original-commit: flang-compiler/f18@23e7a6c27c Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false
This commit is contained in:
parent
c0d3a67fac
commit
b114c58118
|
@ -15,6 +15,7 @@
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "int-power.h"
|
#include "int-power.h"
|
||||||
|
#include "tools.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
#include "../common/idioms.h"
|
#include "../common/idioms.h"
|
||||||
#include "../parser/characters.h"
|
#include "../parser/characters.h"
|
||||||
|
|
|
@ -42,6 +42,8 @@ using common::RelationalOperator;
|
||||||
// wrap discriminated unions.
|
// wrap discriminated unions.
|
||||||
template<typename A> class Expr;
|
template<typename A> class Expr;
|
||||||
|
|
||||||
|
template<typename A> using ResultType = typename std::decay_t<A>::Result;
|
||||||
|
|
||||||
template<typename DERIVED, typename RESULT, typename... OPERAND>
|
template<typename DERIVED, typename RESULT, typename... OPERAND>
|
||||||
class Operation {
|
class Operation {
|
||||||
public:
|
public:
|
||||||
|
@ -597,92 +599,6 @@ public:
|
||||||
u;
|
u;
|
||||||
};
|
};
|
||||||
|
|
||||||
using GenericExpr = Expr<SomeType>; // TODO: delete name?
|
|
||||||
|
|
||||||
template<typename A> using ResultType = typename std::decay_t<A>::Result;
|
|
||||||
|
|
||||||
// Convenience functions and operator overloadings for expression construction.
|
|
||||||
|
|
||||||
template<TypeCategory C, int K>
|
|
||||||
Expr<Type<C, K>> operator-(const Expr<Type<C, K>> &x) {
|
|
||||||
return {Negate<Type<C, K>>{x}};
|
|
||||||
}
|
|
||||||
template<TypeCategory C>
|
|
||||||
Expr<SomeKind<C>> operator-(const Expr<SomeKind<C>> &x) {
|
|
||||||
return std::visit(
|
|
||||||
[](const auto &y) -> Expr<SomeKind<C>> { return {-y}; }, x.u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BINARY(op, CONSTR) \
|
|
||||||
template<TypeCategory C, int K> \
|
|
||||||
Expr<Type<C, K>> operator op( \
|
|
||||||
const Expr<Type<C, K>> &x, const Expr<Type<C, K>> &y) { \
|
|
||||||
return {CONSTR<Type<C, K>>{x, y}}; \
|
|
||||||
} \
|
|
||||||
template<TypeCategory C> \
|
|
||||||
Expr<SomeKind<C>> operator op( \
|
|
||||||
const Expr<SomeKind<C>> &x, const Expr<SomeKind<C>> &y) { \
|
|
||||||
return std::visit( \
|
|
||||||
[](const auto &xk, const auto &yk) -> Expr<SomeKind<C>> { \
|
|
||||||
return {xk op yk}; \
|
|
||||||
}, \
|
|
||||||
x.u, y.u); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BINARY(+, Add)
|
|
||||||
BINARY(-, Subtract)
|
|
||||||
BINARY(*, Multiply)
|
|
||||||
BINARY(/, Divide)
|
|
||||||
#undef BINARY
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define OLDBINARY(FUNC, CONSTR) \
|
|
||||||
template<typename A> A FUNC(const A &x, const A &y) { \
|
|
||||||
return {CONSTR<typename A::Result>{x, y}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(const A &x, A &&y) { \
|
|
||||||
return {CONSTR<typename A::Result>{A{x}, std::move(y)}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(A &&x, const A &y) { \
|
|
||||||
return {CONSTR<typename A::Result>{std::move(x), A{y}}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(A &&x, A &&y) { \
|
|
||||||
return {CONSTR<typename A::Result>{std::move(x), std::move(y)}}; \
|
|
||||||
}
|
|
||||||
#undef OLDBINARY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BINARY(FUNC, OP) \
|
|
||||||
template<typename A> Expr<LogicalResult> FUNC(const A &x, const A &y) { \
|
|
||||||
return {Relational<ResultType<A>>{OP, x, y}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
|
|
||||||
const A &x, A &&y) { \
|
|
||||||
return {Relational<ResultType<A>>{OP, x, std::move(y)}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
|
|
||||||
A &&x, const A &y) { \
|
|
||||||
return {Relational<ResultType<A>>{OP, std::move(x), y}}; \
|
|
||||||
} \
|
|
||||||
template<typename A> \
|
|
||||||
std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
|
|
||||||
A &&x, A &&y) { \
|
|
||||||
return {Relational<ResultType<A>>{OP, std::move(x), std::move(y)}}; \
|
|
||||||
}
|
|
||||||
|
|
||||||
BINARY(operator<, RelationalOperator::LT)
|
|
||||||
BINARY(operator<=, RelationalOperator::LE)
|
|
||||||
BINARY(operator==, RelationalOperator::EQ)
|
|
||||||
BINARY(operator!=, RelationalOperator::NE)
|
|
||||||
BINARY(operator>=, RelationalOperator::GE)
|
|
||||||
BINARY(operator>, RelationalOperator::GT)
|
|
||||||
#undef BINARY
|
|
||||||
|
|
||||||
extern template class Expr<Type<TypeCategory::Character, 1>>; // TODO others
|
extern template class Expr<Type<TypeCategory::Character, 1>>; // TODO others
|
||||||
extern template struct Relational<Type<TypeCategory::Integer, 1>>;
|
extern template struct Relational<Type<TypeCategory::Integer, 1>>;
|
||||||
extern template struct Relational<Type<TypeCategory::Integer, 2>>;
|
extern template struct Relational<Type<TypeCategory::Integer, 2>>;
|
||||||
|
|
|
@ -20,20 +20,9 @@ using namespace Fortran::parser::literals;
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
namespace Fortran::evaluate {
|
||||||
|
|
||||||
Expr<SomeReal> ConvertToTypeOf(
|
|
||||||
const Expr<SomeReal> &to, const Expr<SomeInteger> &from) {
|
|
||||||
return std::visit(
|
|
||||||
[&](const auto &rk) { return Expr<SomeReal>{decltype(rk){to}}; }, to.u);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr<SomeReal> ConvertToTypeOf(
|
|
||||||
const Expr<SomeReal> &to, const Expr<SomeReal> &from) {
|
|
||||||
return std::visit(
|
|
||||||
[&](const auto &rk) { return Expr<SomeReal>{decltype(rk){to}}; }, to.u);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
||||||
parser::ContextualMessages &messages, GenericExpr &&x, GenericExpr &&y) {
|
parser::ContextualMessages &messages, Expr<SomeType> &&x,
|
||||||
|
Expr<SomeType> &&y) {
|
||||||
return std::visit(
|
return std::visit(
|
||||||
common::visitors{[&](Expr<SomeInteger> &&ix, Expr<SomeInteger> &&iy) {
|
common::visitors{[&](Expr<SomeInteger> &&ix, Expr<SomeInteger> &&iy) {
|
||||||
// Can happen in a CMPLX() constructor. Per F'2018,
|
// Can happen in a CMPLX() constructor. Per F'2018,
|
||||||
|
@ -43,11 +32,11 @@ std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
||||||
Expr<SomeReal>{Expr<DefaultReal>{std::move(iy)}})};
|
Expr<SomeReal>{Expr<DefaultReal>{std::move(iy)}})};
|
||||||
},
|
},
|
||||||
[&](Expr<SomeInteger> &&ix, Expr<SomeReal> &&ry) {
|
[&](Expr<SomeInteger> &&ix, Expr<SomeReal> &&ry) {
|
||||||
auto rx{ConvertToTypeOf(ry, std::move(ix))};
|
auto rx{ConvertToTypeAndKindOf(ry, std::move(ix))};
|
||||||
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
|
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
|
||||||
},
|
},
|
||||||
[&](Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
|
[&](Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
|
||||||
auto ry{ConvertToTypeOf(rx, std::move(iy))};
|
auto ry{ConvertToTypeAndKindOf(rx, std::move(iy))};
|
||||||
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
|
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
|
||||||
},
|
},
|
||||||
[&](Expr<SomeReal> &&rx, Expr<SomeReal> &&ry) {
|
[&](Expr<SomeReal> &&rx, Expr<SomeReal> &&ry) {
|
||||||
|
@ -63,8 +52,8 @@ std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
|
||||||
parser::ContextualMessages &messages, std::optional<GenericExpr> &&x,
|
parser::ContextualMessages &messages, std::optional<Expr<SomeType>> &&x,
|
||||||
std::optional<GenericExpr> &&y) {
|
std::optional<Expr<SomeType>> &&y) {
|
||||||
if (x.has_value() && y.has_value()) {
|
if (x.has_value() && y.has_value()) {
|
||||||
return ConvertRealOperands(messages, std::move(*x), std::move(*y));
|
return ConvertRealOperands(messages, std::move(*x), std::move(*y));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,18 +23,92 @@
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
namespace Fortran::evaluate {
|
||||||
|
|
||||||
// Convert the second argument to the same type and kind of the first.
|
// Convenience functions and operator overloadings for expression construction.
|
||||||
Expr<SomeReal> ConvertToTypeOf(
|
template<TypeCategory C, int K>
|
||||||
const Expr<SomeReal> &to, const Expr<SomeInteger> &from);
|
Expr<Type<C, K>> operator-(Expr<Type<C, K>> &&x) {
|
||||||
Expr<SomeReal> ConvertToTypeOf(
|
return {Negate<Type<C, K>>{std::move(x)}};
|
||||||
const Expr<SomeReal> &to, const Expr<SomeReal> &from);
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C, int K>
|
||||||
|
Expr<Type<C, K>> operator+(Expr<Type<C, K>> &&x, Expr<Type<C, K>> &&y) {
|
||||||
|
return {Add<Type<C, K>>{std::move(x), std::move(y)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C, int K>
|
||||||
|
Expr<Type<C, K>> operator-(Expr<Type<C, K>> &&x, Expr<Type<C, K>> &&y) {
|
||||||
|
return {Subtract<Type<C, K>>{std::move(x), std::move(y)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C, int K>
|
||||||
|
Expr<Type<C, K>> operator*(Expr<Type<C, K>> &&x, Expr<Type<C, K>> &&y) {
|
||||||
|
return {Multiply<Type<C, K>>{std::move(x), std::move(y)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C, int K>
|
||||||
|
Expr<Type<C, K>> operator/(Expr<Type<C, K>> &&x, Expr<Type<C, K>> &&y) {
|
||||||
|
return {Divide<Type<C, K>>{std::move(x), std::move(y)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C> Expr<SomeKind<C>> operator-(Expr<SomeKind<C>> &&x) {
|
||||||
|
return std::visit(
|
||||||
|
[](auto &xk) { return Expr<SomeKind<C>>{-std::move(xk)}; }, x.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C>
|
||||||
|
Expr<SomeKind<C>> operator+(Expr<SomeKind<C>> &&x, Expr<SomeKind<C>> &&y) {
|
||||||
|
return std::visit(
|
||||||
|
[](auto &xk, auto &yk) {
|
||||||
|
return Expr<SomeKind<C>>{std::move(xk) + std::move(yk)};
|
||||||
|
},
|
||||||
|
x.u, y.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C>
|
||||||
|
Expr<SomeKind<C>> operator-(Expr<SomeKind<C>> &&x, Expr<SomeKind<C>> &&y) {
|
||||||
|
return std::visit(
|
||||||
|
[](auto &xk, auto &yk) {
|
||||||
|
return Expr<SomeKind<C>>{std::move(xk) - std::move(yk)};
|
||||||
|
},
|
||||||
|
x.u, y.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C>
|
||||||
|
Expr<SomeKind<C>> operator*(Expr<SomeKind<C>> &&x, Expr<SomeKind<C>> &&y) {
|
||||||
|
return std::visit(
|
||||||
|
[](auto &xk, auto &yk) {
|
||||||
|
return Expr<SomeKind<C>>{std::move(xk) * std::move(yk)};
|
||||||
|
},
|
||||||
|
x.u, y.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TypeCategory C>
|
||||||
|
Expr<SomeKind<C>> operator/(Expr<SomeKind<C>> &&x, Expr<SomeKind<C>> &&y) {
|
||||||
|
return std::visit(
|
||||||
|
[](auto &xk, auto &yk) {
|
||||||
|
return Expr<SomeKind<C>>{std::move(xk) / std::move(yk)};
|
||||||
|
},
|
||||||
|
x.u, y.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the second argument expression to an expression of the same type
|
||||||
|
// and kind as that of the first.
|
||||||
|
template<TypeCategory TC, typename F>
|
||||||
|
Expr<SomeKind<TC>> ConvertToTypeAndKindOf(
|
||||||
|
const Expr<SomeKind<TC>> &to, Expr<F> &&from) {
|
||||||
|
return std::visit(
|
||||||
|
[&](const auto &tk) -> Expr<SomeKind<TC>> {
|
||||||
|
using SpecificExpr = std::decay_t<decltype(tk)>;
|
||||||
|
return {SpecificExpr{std::move(from)}};
|
||||||
|
},
|
||||||
|
to.u);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that both operands of an intrinsic REAL operation or CMPLX()
|
// Ensure that both operands of an intrinsic REAL operation or CMPLX()
|
||||||
// are INTEGER or REAL, and convert them as necessary to the same REAL type.
|
// are INTEGER or REAL, and convert them as necessary to the same REAL type.
|
||||||
using ConvertRealOperandsResult =
|
using ConvertRealOperandsResult =
|
||||||
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>>;
|
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>>;
|
||||||
ConvertRealOperandsResult ConvertRealOperands(
|
ConvertRealOperandsResult ConvertRealOperands(
|
||||||
parser::ContextualMessages &, GenericExpr &&, GenericExpr &&);
|
parser::ContextualMessages &, Expr<SomeType> &&, Expr<SomeType> &&);
|
||||||
|
|
||||||
template<TypeCategory CAT>
|
template<TypeCategory CAT>
|
||||||
void ConvertToSameKind(Expr<SomeKind<CAT>> &x, Expr<SomeKind<CAT>> &y) {
|
void ConvertToSameKind(Expr<SomeKind<CAT>> &x, Expr<SomeKind<CAT>> &y) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
|
#include "tools.h"
|
||||||
#include "../common/idioms.h"
|
#include "../common/idioms.h"
|
||||||
#include "../parser/char-block.h"
|
#include "../parser/char-block.h"
|
||||||
#include "../parser/characters.h"
|
#include "../parser/characters.h"
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Fortran::semantics {
|
||||||
|
|
||||||
using common::TypeCategory;
|
using common::TypeCategory;
|
||||||
using evaluate::Expr;
|
using evaluate::Expr;
|
||||||
using evaluate::GenericExpr;
|
using evaluate::SomeType;
|
||||||
using evaluate::Type;
|
using evaluate::Type;
|
||||||
|
|
||||||
using MaybeIntExpr = std::optional<Expr<evaluate::SomeInteger>>;
|
using MaybeIntExpr = std::optional<Expr<evaluate::SomeInteger>>;
|
||||||
|
@ -117,8 +117,8 @@ static std::optional<Expr<evaluate::SomeCharacter>> AnalyzeLiteral(
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A> MaybeExpr PackageGeneric(std::optional<A> &&x) {
|
template<typename A> MaybeExpr PackageGeneric(std::optional<A> &&x) {
|
||||||
std::function<GenericExpr(A &&)> f{
|
std::function<Expr<SomeType>(A &&)> f{
|
||||||
[](A &&y) { return GenericExpr{std::move(y)}; }};
|
[](A &&y) { return Expr<SomeType>{std::move(y)}; }};
|
||||||
return common::MapOptional(f, std::move(x));
|
return common::MapOptional(f, std::move(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ MaybeExpr AnalyzeHelper(
|
||||||
evaluate::CopyableIndirection<evaluate::Substring> ind{std::move(substring)};
|
evaluate::CopyableIndirection<evaluate::Substring> ind{std::move(substring)};
|
||||||
Expr<evaluate::DefaultCharacter> chExpr{std::move(ind)};
|
Expr<evaluate::DefaultCharacter> chExpr{std::move(ind)};
|
||||||
chExpr.Fold(ea.context());
|
chExpr.Fold(ea.context());
|
||||||
return {GenericExpr{Expr<evaluate::SomeCharacter>{std::move(chExpr)}}};
|
return {Expr<SomeType>{Expr<evaluate::SomeCharacter>{std::move(chExpr)}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
|
// Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
|
||||||
|
@ -269,7 +269,7 @@ static std::optional<Expr<evaluate::SomeReal>> AnalyzeLiteral(
|
||||||
AnalyzeLiteral(ea, std::get<parser::RealLiteralConstant>(x.t))}) {
|
AnalyzeLiteral(ea, std::get<parser::RealLiteralConstant>(x.t))}) {
|
||||||
if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
|
if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
|
||||||
if (sign == parser::Sign::Negative) {
|
if (sign == parser::Sign::Negative) {
|
||||||
return {-*result};
|
return {-std::move(*result)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -577,12 +577,12 @@ ExpressionAnalyzer::KindParam ExpressionAnalyzer::Analyze(
|
||||||
std::optional<Expr<evaluate::SomeComplex>> ExpressionAnalyzer::ConstructComplex(
|
std::optional<Expr<evaluate::SomeComplex>> ExpressionAnalyzer::ConstructComplex(
|
||||||
MaybeExpr &&real, MaybeExpr &&imaginary) {
|
MaybeExpr &&real, MaybeExpr &&imaginary) {
|
||||||
// TODO: pmk abstract further, this will be a common pattern
|
// TODO: pmk abstract further, this will be a common pattern
|
||||||
auto partial{[&](GenericExpr &&x, GenericExpr &&y) {
|
auto partial{[&](Expr<SomeType> &&x, Expr<SomeType> &&y) {
|
||||||
return evaluate::ConvertRealOperands(
|
return evaluate::ConvertRealOperands(
|
||||||
context_.messages, std::move(x), std::move(y));
|
context_.messages, std::move(x), std::move(y));
|
||||||
}};
|
}};
|
||||||
using fType =
|
using fType =
|
||||||
evaluate::ConvertRealOperandsResult(GenericExpr &&, GenericExpr &&);
|
evaluate::ConvertRealOperandsResult(Expr<SomeType> &&, Expr<SomeType> &&);
|
||||||
std::function<fType> f{partial};
|
std::function<fType> f{partial};
|
||||||
auto converted{common::MapOptional(f, std::move(real), std::move(imaginary))};
|
auto converted{common::MapOptional(f, std::move(real), std::move(imaginary))};
|
||||||
if (auto joined{common::JoinOptionals(std::move(converted))}) {
|
if (auto joined{common::JoinOptionals(std::move(converted))}) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace Fortran::semantics {
|
namespace Fortran::semantics {
|
||||||
|
|
||||||
using MaybeExpr = std::optional<evaluate::GenericExpr>;
|
using MaybeExpr = std::optional<evaluate::Expr<evaluate::SomeType>>;
|
||||||
|
|
||||||
class ExpressionAnalyzer {
|
class ExpressionAnalyzer {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "../../lib/evaluate/expression.h"
|
#include "../../lib/evaluate/expression.h"
|
||||||
|
#include "../../lib/evaluate/tools.h"
|
||||||
#include "testing.h"
|
#include "testing.h"
|
||||||
#include "../../lib/parser/message.h"
|
#include "../../lib/parser/message.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -41,11 +42,9 @@ int main() {
|
||||||
FoldingContext context{messages};
|
FoldingContext context{messages};
|
||||||
ex1.Fold(context);
|
ex1.Fold(context);
|
||||||
MATCH("-10_4", Dump(ex1));
|
MATCH("-10_4", Dump(ex1));
|
||||||
MATCH("(6_4.LE.7_4)",
|
MATCH("(1_4/2_4)", Dump(DefaultIntegerExpr{1} / DefaultIntegerExpr{2}));
|
||||||
Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7}));
|
|
||||||
DefaultIntegerExpr a{1};
|
DefaultIntegerExpr a{1};
|
||||||
DefaultIntegerExpr b{2};
|
DefaultIntegerExpr b{2};
|
||||||
MATCH("(1_4/2_4)", Dump(a / b));
|
|
||||||
MATCH("1_4", Dump(a));
|
MATCH("1_4", Dump(a));
|
||||||
a = b;
|
a = b;
|
||||||
MATCH("2_4", Dump(a));
|
MATCH("2_4", Dump(a));
|
||||||
|
|
Loading…
Reference in New Issue