From 06fe2669985a8f18796f66e18d04b5cc235f11cb Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 3 Jul 2018 15:14:48 -0700 Subject: [PATCH] [flang] work on variables and traversal Original-commit: flang-compiler/f18@432779b2218c500a18dec7f1018270bf150be0cb Reviewed-on: https://github.com/flang-compiler/f18/pull/117 Tree-same-pre-rewrite: false --- flang/documentation/FortranForCProgrammers.md | 6 +- flang/lib/evaluate/expression.cc | 29 +++-- flang/lib/evaluate/expression.h | 139 ++++++++++++++++-------- flang/lib/evaluate/variable.h | 150 ++++++++++++++++++++++---- 4 files changed, 249 insertions(+), 75 deletions(-) diff --git a/flang/documentation/FortranForCProgrammers.md b/flang/documentation/FortranForCProgrammers.md index 0ffa8a0..0512376 100644 --- a/flang/documentation/FortranForCProgrammers.md +++ b/flang/documentation/FortranForCProgrammers.md @@ -54,8 +54,10 @@ Data Types There are five built-in ("intrinsic") types: `INTEGER`, `REAL`, `COMPLEX`, `LOGICAL`, and `CHARACTER`. They are parameterized with "kind" values, which should be treated as -non-portable integer codes but in practice today are the byte sizes of +non-portable integer codes, although in practice today are the byte sizes of the data. +(For `COMPLEX`, the kind type parameter value is the byte size of one of the +two `REAL` components, or half of the total size.) The legacy `DOUBLE PRECISION` intrinsic type is an alias for a kind of `REAL` that should be bigger than the default `REAL`. @@ -86,7 +88,7 @@ where type is not necessary. Arrays ------ Arrays are not a type in Fortran. -Being an array is a property of an object, not of a type. +Being an array is a property of an object or function, not of a type. Unlike C, one cannot have an array of arrays or an array of pointers, although can can have an array of a derived type that has arrays or pointers as components. diff --git a/flang/lib/evaluate/expression.cc b/flang/lib/evaluate/expression.cc index d50e8ff..1927fbc 100644 --- a/flang/lib/evaluate/expression.cc +++ b/flang/lib/evaluate/expression.cc @@ -43,7 +43,12 @@ std::ostream &AnyCharacterExpr::Dump(std::ostream &o) const { return o; } -std::ostream &AnyIntegerOrRealExpr::Dump(std::ostream &o) const { +std::ostream &AnyComplexExpr::Dump(std::ostream &o) const { + std::visit([&](const auto &x) { x.Dump(o); }, u); + return o; +} + +std::ostream &AnyExpr::Dump(std::ostream &o) const { std::visit([&](const auto &x) { x.Dump(o); }, u); return o; } @@ -62,7 +67,8 @@ template std::ostream &IntegerExpr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const Constant &n) { o << n.SignedDecimal(); }, - [&](const Convert &c) { c.x->Dump(o); }, + [&](const Convert &j) { j.x->Dump(o); }, + [&](const Convert &a) { a.x->Dump(o); }, [&](const Parentheses &p) { p.Dump(o, "("); }, [&](const Negate &n) { n.Dump(o, "(-"); }, [&](const Add &a) { a.Dump(o, "+"); }, @@ -78,13 +84,13 @@ template void IntegerExpr::Fold( const parser::CharBlock &at, parser::Messages *messages) { std::visit(common::visitors{[&](const Parentheses &p) { - p.Mutable()->Fold(at, messages); + p.x->Fold(at, messages); if (auto c{std::get_if(&p.x->u)}) { u = *c; } }, [&](const Negate &n) { - n.Mutable()->Fold(at, messages); + n.x->Fold(at, messages); if (auto c{std::get_if(&n.x->u)}) { auto negated{c->Negate()}; if (negated.overflow && messages != nullptr) { @@ -94,8 +100,8 @@ void IntegerExpr::Fold( } }, [&](const Add &a) { - a.MutableX()->Fold(at, messages); - a.MutableY()->Fold(at, messages); + a.x->Fold(at, messages); + a.y->Fold(at, messages); if (auto xc{std::get_if(&a.x->u)}) { if (auto yc{std::get_if(&a.y->u)}) { auto sum{xc->AddSigned(*yc)}; @@ -107,8 +113,8 @@ void IntegerExpr::Fold( } }, [&](const Multiply &a) { - a.MutableX()->Fold(at, messages); - a.MutableY()->Fold(at, messages); + a.x->Fold(at, messages); + a.y->Fold(at, messages); if (auto xc{std::get_if(&a.x->u)}) { if (auto yc{std::get_if(&a.y->u)}) { auto product{xc->MultiplySigned(*yc)}; @@ -122,8 +128,8 @@ void IntegerExpr::Fold( } }, [&](const Bin &b) { - b.MutableX()->Fold(at, messages); - b.MutableY()->Fold(at, messages); + b.x->Fold(at, messages); + b.y->Fold(at, messages); }, [&](const auto &) { // TODO: more }}, @@ -133,7 +139,8 @@ void IntegerExpr::Fold( template std::ostream &RealExpr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); }, - [&](const Convert &c) { c.x->Dump(o); }, + [&](const Convert &j) { j.x->Dump(o); }, + [&](const Convert &a) { a.x->Dump(o); }, [&](const Parentheses &p) { p.Dump(o, "("); }, [&](const Negate &n) { n.Dump(o, "(-"); }, [&](const Add &a) { a.Dump(o, "+"); }, diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 5550e20..950e2ae 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -43,13 +43,12 @@ struct AnyIntegerExpr; struct AnyRealExpr; struct AnyComplexExpr; struct AnyCharacterExpr; -struct AnyIntegerOrRealExpr; // Helper base classes to manage subexpressions, which are known as data members // named 'x' and, for binary operations, 'y'. template struct Unary { Unary(const A &a) : x{std::make_unique(a)} {} - Unary(std::unique_ptr &&a) : x{std::move(a)} {} + Unary(std::unique_ptr &&a) : x{std::move(a)} {} Unary(A &&a) : x{std::make_unique(std::move(a))} {} Unary(const Unary &that) : x{std::make_unique(*that.x)} {} Unary(Unary &&) = default; @@ -58,9 +57,8 @@ template struct Unary { return *this; } Unary &operator=(Unary &&) = default; - A *Mutable() const { return const_cast(x.get()); } std::ostream &Dump(std::ostream &, const char *opr) const; - std::unique_ptr x; + std::unique_ptr x; }; template struct Binary { @@ -80,19 +78,15 @@ template struct Binary { return *this; } Binary &operator=(Binary &&) = default; - A *MutableX() const { return const_cast(x.get()); } - B *MutableY() const { return const_cast(y.get()); } std::ostream &Dump(std::ostream &, const char *opr) const; - std::unique_ptr x; - std::unique_ptr y; + std::unique_ptr x; + std::unique_ptr y; }; template struct IntegerExpr { using Result = Type; using Constant = typename Result::Value; - struct Convert : Unary { - using Unary::Unary; - }; + template struct Convert : Unary { using Unary::Unary; }; using Un = Unary; using Bin = Binary; struct Parentheses : public Un { @@ -123,15 +117,29 @@ template struct IntegerExpr { IntegerExpr(const Constant &x) : u{x} {} IntegerExpr(std::int64_t n) : u{Constant{n}} {} IntegerExpr(int n) : u{Constant{n}} {} - template IntegerExpr(A &&x) : u{std::move(x)} {} + template + IntegerExpr(const IntegerExpr &x) + : u{Convert{AnyIntegerExpr{x}}} {} + template + IntegerExpr(IntegerExpr &&x) + : u{Convert{AnyIntegerExpr{std::move(x)}}} {} + template + IntegerExpr(const RealExpr &x) : u{Convert{AnyRealExpr{x}}} {} + template + IntegerExpr(RealExpr &&x) + : u{Convert{AnyRealExpr{std::move(x)}}} {} + template IntegerExpr(const A &x) : u{x} {} + template + IntegerExpr(std::enable_if_t, A> &&x) + : u(std::move(x)) {} IntegerExpr &operator=(const IntegerExpr &) = default; IntegerExpr &operator=(IntegerExpr &&) = default; std::ostream &Dump(std::ostream &) const; void Fold(const parser::CharBlock &, parser::Messages *); - std::variant + std::variant, Convert, + Parentheses, Negate, Add, Subtract, Multiply, Divide, Power> u; }; @@ -143,9 +151,7 @@ template struct RealExpr { // N.B. Real->Complex and Complex->Real conversions are done with CMPLX // and part access operations (resp.). Conversions between kinds of // Complex are done via decomposition to Real and reconstruction. - struct Convert : Unary { - using Unary::Unary; - }; + template struct Convert : Unary { using Unary::Unary; }; using Un = Unary; using Bin = Binary; struct Parentheses : public Un { @@ -184,14 +190,29 @@ template struct RealExpr { RealExpr(const RealExpr &) = default; RealExpr(RealExpr &&) = default; RealExpr(const Constant &x) : u{x} {} - template RealExpr(A &&x) : u{std::move(x)} {} + template + RealExpr(const IntegerExpr &x) + : u{Convert{AnyIntegerExpr{x}}} {} + template + RealExpr(IntegerExpr &&x) + : u{Convert{AnyIntegerExpr{std::move(x)}}} {} + template + RealExpr(const RealExpr &x) : u{Convert{AnyRealExpr{x}}} {} + template + RealExpr(RealExpr &&x) + : u{Convert{AnyRealExpr{std::move(x)}}} {} + template RealExpr(const A &x) : u{x} {} + template + RealExpr(std::enable_if_t, A> &&x) + : u{std::move(x)} {} RealExpr &operator=(const RealExpr &) = default; RealExpr &operator=(RealExpr &&) = default; std::ostream &Dump(std::ostream &) const; - std::variant + std::variant, Convert, + Parentheses, Negate, Add, Subtract, Multiply, Divide, Power, IntPower, + RealPart, AIMAG> u; }; @@ -232,7 +253,10 @@ template struct ComplexExpr { ComplexExpr(const ComplexExpr &) = default; ComplexExpr(ComplexExpr &&) = default; ComplexExpr(const Constant &x) : u{x} {} - template ComplexExpr(A &&x) : u{std::move(x)} {} + template ComplexExpr(const A &x) : u{x} {} + template + ComplexExpr(std::enable_if_t, A> &&x) + : u{std::move(x)} {} ComplexExpr &operator=(const ComplexExpr &) = default; ComplexExpr &operator=(ComplexExpr &&) = default; @@ -256,11 +280,12 @@ template struct CharacterExpr { CharacterExpr(CharacterExpr &&) = default; CharacterExpr(const Constant &x) : u{x} {} CharacterExpr(Constant &&x) : u{std::move(x)} {} + CharacterExpr(const Concat &x) : u{x} {} CharacterExpr(Concat &&x) : u{std::move(x)} {} CharacterExpr &operator=(const CharacterExpr &) = default; CharacterExpr &operator=(CharacterExpr &&) = default; - IntegerExpr LEN() const; + LengthExpr LEN() const; std::ostream &Dump(std::ostream &) const; std::variant u; @@ -292,7 +317,10 @@ template struct Comparison { Comparison() = delete; Comparison(const Comparison &) = default; Comparison(Comparison &&) = default; - template Comparison(A &&x) : u{std::move(x)} {} + template Comparison(const A &x) : u{x} {} + template + Comparison(std::enable_if_t, A> &&x) + : u{std::move(x)} {} Comparison &operator=(const Comparison &) = default; Comparison &operator=(Comparison &&) = default; @@ -314,7 +342,10 @@ template struct Comparison> { Comparison() = delete; Comparison(const Comparison &) = default; Comparison(Comparison &&) = default; - template Comparison(A &&x) : u{std::move(x)} {} + template Comparison(const A &x) : u{x} {} + template + Comparison(std::enable_if_t, A> &&x) + : u{std::move(x)} {} Comparison &operator=(const Comparison &) = default; Comparison &operator=(Comparison &&) = default; @@ -327,6 +358,7 @@ struct IntegerComparison { IntegerComparison() = delete; IntegerComparison(const IntegerComparison &) = default; IntegerComparison(IntegerComparison &&) = default; + template IntegerComparison(const A &x) : u{x} {} template IntegerComparison(A &&x) : u{std::move(x)} {} IntegerComparison &operator=(const IntegerComparison &) = default; IntegerComparison &operator=(IntegerComparison &&) = default; @@ -339,7 +371,10 @@ struct RealComparison { RealComparison() = delete; RealComparison(const RealComparison &) = default; RealComparison(RealComparison &&) = default; - template RealComparison(A &&x) : u{std::move(x)} {} + template RealComparison(const A &x) : u{x} {} + template + RealComparison(std::enable_if_t, A> &&x) + : u{std::move(x)} {} RealComparison &operator=(const RealComparison &) = default; RealComparison &operator=(RealComparison &&) = default; std::ostream &Dump(std::ostream &) const; @@ -350,7 +385,10 @@ struct RealComparison { struct ComplexComparison { ComplexComparison() = delete; ComplexComparison(ComplexComparison &&) = default; - template ComplexComparison(A &&x) : u{std::move(x)} {} + template ComplexComparison(const A &x) : u{x} {} + template + ComplexComparison(std::enable_if_t, A> &&x) + : u{std::move(x)} {} ComplexComparison &operator=(const ComplexComparison &) = default; ComplexComparison &operator=(ComplexComparison &&) = default; std::ostream &Dump(std::ostream &) const; @@ -362,7 +400,10 @@ struct CharacterComparison { CharacterComparison() = delete; CharacterComparison(const CharacterComparison &) = default; CharacterComparison(CharacterComparison &&) = default; - template CharacterComparison(A &&x) : u{std::move(x)} {} + template CharacterComparison(const A &x) : u{x} {} + template + CharacterComparison(std::enable_if_t, A> &&x) + : u{std::move(x)} {} CharacterComparison &operator=(const CharacterComparison &) = default; CharacterComparison &operator=(CharacterComparison &&) = default; std::ostream &Dump(std::ostream &) const; @@ -417,7 +458,10 @@ struct LogicalExpr { template LogicalExpr(Comparison> &&x) : u{CharacterComparison{std::move(x)}} {} - template LogicalExpr(A &&x) : u{std::move(x)} {} + template LogicalExpr(const A &x) : u{x} {} + template + LogicalExpr(std::enable_if_t, A> &&x) + : u{std::move(x)} {} LogicalExpr &operator=(const LogicalExpr &) = default; LogicalExpr &operator=(LogicalExpr &&) = default; @@ -475,27 +519,34 @@ struct AnyCharacterExpr { CharacterKindsVariant u; }; -struct AnyIntegerOrRealExpr { - AnyIntegerOrRealExpr() = delete; - AnyIntegerOrRealExpr(const AnyIntegerOrRealExpr &) = default; - AnyIntegerOrRealExpr(AnyIntegerOrRealExpr &&) = default; +struct AnyExpr { + AnyExpr() = delete; + AnyExpr(const AnyExpr &) = default; + AnyExpr(AnyExpr &&) = default; + template + AnyExpr(const IntegerExpr &x) : u{AnyIntegerExpr{x}} {} template - AnyIntegerOrRealExpr(const IntegerExpr &x) : u{AnyIntegerExpr{x}} {} + AnyExpr(IntegerExpr &&x) : u{AnyIntegerExpr{std::move(x)}} {} + template AnyExpr(const RealExpr &x) : u{AnyRealExpr{x}} {} template - AnyIntegerOrRealExpr(IntegerExpr &&x) - : u{AnyIntegerExpr{std::move(x)}} {} + AnyExpr(RealExpr &&x) : u{AnyRealExpr{std::move(x)}} {} template - AnyIntegerOrRealExpr(const RealExpr &x) : u{AnyRealExpr{x}} {} + AnyExpr(const ComplexExpr &x) : u{AnyComplexExpr{x}} {} template - AnyIntegerOrRealExpr(RealExpr &&x) : u{AnyRealExpr{std::move(x)}} {} - AnyIntegerOrRealExpr(const AnyIntegerExpr &x) : u{x} {} - AnyIntegerOrRealExpr(AnyIntegerExpr &&x) : u{std::move(x)} {} - AnyIntegerOrRealExpr(const AnyRealExpr &x) : u{x} {} - AnyIntegerOrRealExpr(AnyRealExpr &&x) : u{std::move(x)} {} - AnyIntegerOrRealExpr &operator=(const AnyIntegerOrRealExpr &) = default; - AnyIntegerOrRealExpr &operator=(AnyIntegerOrRealExpr &&) = default; + AnyExpr(ComplexExpr &&x) : u{AnyComplexExpr{std::move(x)}} {} + template + AnyExpr(const CharacterExpr &x) : u{AnyCharacterExpr{x}} {} + template + AnyExpr(CharacterExpr &&x) : u{AnyCharacterExpr{std::move(x)}} {} + template AnyExpr(const A &x) : u{x} {} + template + AnyExpr(std::enable_if_t, A> &&x) : u{std::move(x)} {} + AnyExpr &operator=(const AnyExpr &) = default; + AnyExpr &operator=(AnyExpr &&) = default; std::ostream &Dump(std::ostream &) const; - std::variant u; + std::variant + u; }; // Convenience functions and operator overloadings for expression construction. diff --git a/flang/lib/evaluate/variable.h b/flang/lib/evaluate/variable.h index 7895aaa..286b708 100644 --- a/flang/lib/evaluate/variable.h +++ b/flang/lib/evaluate/variable.h @@ -16,53 +16,167 @@ #define FORTRAN_EVALUATE_VARIABLE_H_ #include "expression.h" +#include "traverse.h" #include #include #include +#include namespace Fortran::evaluate { -struct Designator; +struct DataRef; +struct Variable; +struct ActualArg; +struct Label; // TODO -struct DataObject { - semantics::Symbol &object; -}; +using semantics::Symbol; struct Component { - semantics::Symbol &component; - std::variant, std::unique_ptr>> u; + Component(const Symbol &c, std::unique_ptr &&b) + : sym{c}, base{std::move(b)} {} + const Symbol &sym; + template void DefaultTraverse(V &v) { v(base); } + std::unique_ptr base; }; using SubscriptExpr = DefaultIntExpr; struct Triplet { - std::optional lower, upper, stride; + Triplet(std::optional &&l, std::optional &&u, + std::optional &&s) + : lower{std::move(l)}, upper{std::move(u)}, stride{std::move(s)} {} + template void DefaultTraverse(V &v) { + v(lower); + v(upper); + v(stride); + } + std::optional lower, upper, stride; }; struct Subscript { - std::variant; + Subscript() = delete; + explicit Subscript(SubscriptExpr &&s) : u{std::move(s)} {} + explicit Subscript(Triplet &&t) : u{std::move(t)} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant u; }; -struct Subscripted { - std::vector> subscript; - std::variant, std::unique_ptr> u; +struct ArrayRef { + ArrayRef() = delete; + ArrayRef(const Symbol &n, std::vector &&s) + : u{n}, subscript{std::move(ss)} {} + ArrayRef(Component &&c, std::vector &&s) + : u{std::move(c)}, subscript{std::move(ss)} {} + template void DefaultTraverse(V &v) { + v(u); + v(subscript); + } + std::variant u; + std::vector subscript; }; struct CoarrayRef { - std::vector>; - // TODO R926 image selector specs - std::variant, std::unique_ptr, - std::unique_ptr> u; + CoarrayRef() = delete; + CoarrayRef(const Symbol &n, std::vector &&s) + : u{n}, cosubscript{std::move(s)} {} + CoarrayRef(Component &&c, std::vector &&s) + : u{std::move(c)}, cosubscript{std::move(s)} {} + CoarrayRef(ArrayRef &&a, std::vector &&s) + : u{std::move(a)}, cosubscript{std::move(s)} {} + template void DefaultTraverse(V &v) { + v(u); + v(cosubscript); + v(stat); + v(team); + v(teamNumber); + } + std::variant u; + std::vector cosubscript; + std::unique_ptr stat, team, teamNumber; // nullable +}; + +struct DataRef { + DataRef() = delete; + explicit DataRef(const Symbol &n) : u{n} {} + explicit DataRef(Component &&c) : u{std::move(c)} {} + explicit DataRef(ArrayRef &&a) : u{std::move(a)} {} + explicit DataRef(CoarrayRef &&c) : u{std::move(c)} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant u; +}; + +struct Substring { + Substring() = delete; + Substring(DataRef &&d, std::optional &&f, + std::optional &&l) + : u{std::move(d)}, first{std::move(f)}, last{std::move(l)} {} + Substring(std::string &&s, std::optional &&f, + std::optional &&l) + : u{std::move(s)}, first{std::move(f)}, last{std::move(l)} {} + template void DefaultTraverse(V &v) { + v(u); + v(first); + v(last); + } + std::variant u; + std::optional first, last; +}; + +struct ComplexPart { + enum class Part { RE, IM }; + ComplexPart(DataRef &&z, Part p) : complex{std::move(z)}, part{p} {} + template void DefaultTraverse(V &v) { v(complex); } + DataRef complex; + Part part; }; struct Designator { Designator() = delete; - std::variant, std::unique_ptr, - std::unique_ptr, std::unique_ptr> u; + explicit Designator(DataRef &&d) : u{std::move(d)} {} + explicit Designator(Substring &&s) : u{std::move(s)} {} + explicit Designator(ComplexPart &&c) : u{std::move(c)} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant u; }; -struct Substring { +struct ProcedureDesignator { + ProcedureDesignator() = delete; + ProcedureDesignator(std::unique_ptr &&v, const Symbol &n) + : u{std::move(v)}, sym{n} {} + ProcedureDesignator(DataRef &&d, const Symbol &n) : u{std::move(d)}, sym{n} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant, DataRef> u; + const Symbol &sym; +}; + +struct ProcedureRef { + ProcedureRef() = delete; + ProcedureRef( + ProcedureDesignator &&p, std::vector> &&a) + : proc{std::move(p)}, arg{std::move(a)} {} + template void DefaultTraverse(V &v) { + v(proc); + v(arg); + } + ProcedureDesignator proc; + std::vector> arg; // nullable }; +struct Variable { + Variable() = delete; + explicit Variable(Designator &&d) : u{std::move(u)} {} + explicit Variable(ProcedureRef &&p) : u{std::move(p)} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant u; +}; + +struct ActualArg { + ActualArg() = delete; + explicit ActualArg(AnyExpr &&x) : u{std::move(x)} {} + explicit ActualArg(Variable &&x) : u{std::move(x)} {} + explicit ActualArg(const Label &l) : u{l} {} + template void DefaultTraverse(V &v) { v(u); } + std::variant u; +}; } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_VARIABLE_H_ -- 2.7.4