integer.cc
logical.cc
real.cc
+ type.cc
)
target_link_libraries(FortranEvaluate
Part im{im1.Divide(den).AccumulateFlags(flags)};
return {Complex{re, im}, flags};
}
+
+template<typename R> std::string Complex<R>::DumpHexadecimal() const {
+ std::string result{'('};
+ result += re_.DumpHexadecimal();
+ result += ',';
+ result += im_.DumpHexadecimal();
+ result += ')';
+ return result;
+}
} // namespace Fortran::evaluate::value
#define FORTRAN_EVALUATE_COMPLEX_H_
#include "real.h"
+#include <string>
namespace Fortran::evaluate::value {
ValueWithRealFlags<Complex> Multiply(const Complex &) const;
ValueWithRealFlags<Complex> Divide(const Complex &) const;
+ std::string DumpHexadecimal() const;
// TODO: (C)ABS once Real::HYPOT is done
// TODO: unit testing
#include "../common/idioms.h"
#include <ostream>
#include <string>
+#include <type_traits>
namespace Fortran::evaluate {
-template<Category C, int KIND>
-void NumericBase<C, KIND>::dump(std::ostream &o) const {}
+template<int KIND> std::ostream &IntExpr<KIND>::Dump(std::ostream &o) const {
+ std::visit(
+ common::visitors{[&](const Constant &n) { o << n.SignedDecimal(); },
+ [&](const Convert &c) {
+ o << "convert(";
+ std::visit(
+ [&](const auto &x) { // x is IntegerOperand or RealOperand
+ std::visit(
+ [&](const auto &y) { // y is ExprOperand<Type<C,K>>
+ using Expr =
+ typename std::remove_reference<decltype(*y)>::type;
+ using Ty = typename Expr::Result;
+ y->Dump(o << Ty::Dump() << ' ');
+ },
+ x.u);
+ },
+ c.u);
+ o << ')';
+ },
+ [&](const Parentheses &p) { p.x->Dump(o << '(') << ')'; },
+ [&](const Negate &n) { n.x->Dump(o << "(-") << ')'; },
+ [&](const Add &a) { a.y->Dump(a.x->Dump(o << '(') << '+') << ')'; },
+ [&](const Subtract &s) {
+ s.y->Dump(s.x->Dump(o << '(') << '-') << ')';
+ },
+ [&](const Multiply &m) {
+ m.y->Dump(m.x->Dump(o << '(') << '*') << ')';
+ },
+ [&](const Divide &d) {
+ d.y->Dump(d.x->Dump(o << '(') << '/') << ')';
+ },
+ [&](const Power &p) {
+ p.y->Dump(p.x->Dump(o << '(') << "**") << ')';
+ }},
+ u);
+ return o;
+}
+
+template<int KIND> std::ostream &RealExpr<KIND>::Dump(std::ostream &o) const {
+ std::visit(
+ common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); },
+ [&](const auto &) { o << "TODO"; }},
+ u);
+ return o;
+}
template<int KIND> typename CharExpr<KIND>::Length CharExpr<KIND>::LEN() const {
return std::visit(
// struct Add { Operand x, y; };
// a data member to hold an instance of one of these structs:
// std::variant<> u;
-// and a formatting member function, dump().
+// and a formatting member function, Dump().
template<typename T> struct Expression;
template<typename T> struct ExprOperand {
struct Power {
Operand x, y;
};
-
- void dump(std::ostream &) const;
};
template<int KIND>
using Power = typename Base::Power;
Expression() = delete;
Expression(Expression &&) = default;
- Expression(const typename Base::Constant &x) : u{x} {}
+ Expression(const Constant &x) : u{x} {}
+ Expression(std::int64_t n) : u{Constant{n}} {}
+ Expression(int n) : u{Constant{n}} {}
template<typename A> Expression(A &&x) : u{std::move(x)} {}
+ std::ostream &Dump(std::ostream &) const;
std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
Divide, Power>
u;
Expression(Expression &&) = default;
Expression(const Constant &x) : u{x} {}
template<typename A> Expression(A &&x) : u{std::move(x)} {}
+ std::ostream &Dump(std::ostream &) const;
std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
Divide, Power, IntegerPower, RealPart, AIMAG>
u;
Expression(Expression &&) = default;
Expression(const Constant &x) : u{x} {}
template<typename A> Expression(A &&x) : u{std::move(x)} {}
+ std::ostream &Dump(std::ostream &) const;
std::variant<Constant, Parentheses, Negate, Add, Subtract, Multiply, Divide,
Power, IntegerPower, CMPLX>
u;
return {typename Comparison<T>::GT{std::move(x), std::move(y)}};
}
+ std::ostream &Dump(std::ostream &) const;
+
std::variant<Constant, Not, And, Or, Eqv, Neqv, IntegerComparison,
RealComparison, ComplexComparison, CharacterComparison>
u;
Expression(Expression &&a, Expression &&b)
: u{Concat{std::move(a), std::move(b)}} {}
Length LEN() const;
+ std::ostream &Dump(std::ostream &) const;
std::variant<Constant, Concat> u;
};
u;
};
-// Convenience operator overloadings for expression construction.
+// Convenience functions and operator overloadings for expression construction.
+template<typename A> Expression<A> Parentheses(Expression<A> &&x) {
+ return {typename Expression<A>::Parentheses{std::move(x)}};
+}
template<typename A> Expression<A> operator-(Expression<A> &&x) {
return {typename Expression<A>::Negate{std::move(x)}};
}
Expression<A> operator/(Expression<A> &&x, Expression<A> &&y) {
return {typename Expression<A>::Divide{std::move(x), std::move(y)}};
}
+template<typename A> Expression<A> Power(Expression<A> &&x, Expression<A> &&y) {
+ return {typename Expression<A>::Power{std::move(x), std::move(y)}};
+}
+
+// TODO: comparison generators
extern template struct Expression<Type<Category::Integer, 1>>;
extern template struct Expression<Type<Category::Integer, 2>>;
--- /dev/null
+// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "type.h"
+#include <string>
+
+namespace Fortran::evaluate {
+
+std::string CategoryName(Category c) {
+ switch (c) {
+ case Category::Integer: return "Integer";
+ case Category::Real: return "Real";
+ case Category::Complex: return "Complex";
+ case Category::Logical: return "Logical";
+ case Category::Character: return "Character";
+ case Category::Derived: return "Derived";
+ }
+ return ""; // placate g++
+}
+} // namespace Fortran::evaluate
namespace Fortran::evaluate {
-enum class Category { Integer, Real, Complex, Character, Logical, Derived };
+enum class Category { Integer, Real, Complex, Logical, Character, Derived };
+
+std::string CategoryName(Category);
template<Category C, int KIND> struct TypeBase {
static constexpr Category category{C};
static constexpr int kind{KIND};
static constexpr bool hasLen{false};
+ static std::string Dump() {
+ return CategoryName(category) + '(' + std::to_string(kind) + ')';
+ }
};
template<Category C, int KIND> struct Type;
#include "testing.h"
#include <cstdio>
#include <cstdlib>
+#include <sstream>
+#include <iostream> // TODO pmk rm
using namespace Fortran::evaluate;
int main() {
using Int4 = Type<Category::Integer, 4>;
+ TEST(Int4::Dump() == "Integer(4)");
using IntEx4 = Expression<Int4>;
- IntEx4 ie{value::Integer<32>(666)};
- IntEx4 one{value::Integer<32>(1)};
- IntEx4 incr{IntEx4::Add{std::move(ie), std::move(one)}};
+ IntEx4 ie{666};
+ std::stringstream ss;
+ ie.Dump(ss);
+ TEST(ss.str() == "666");
+ IntEx4 one{IntEx4::Constant{1}};
+ IntEx4 incr{std::move(ie) + IntEx4{1}};
+incr.Dump(std::cout) << '\n';
using Log = Expression<Type<Category::Logical, 1>>;
- IntEx4 two{value::Integer<32>(2)};
- Log cmp{Log::EQ(std::move(incr), std::move(two))};
+ Log cmp{Log::EQ(std::move(incr), IntEx4{2})};
return testing::Complete();
}