[flang] Refactor some lib/evaluate headers for sanity

Original-commit: flang-compiler/f18@9530378c39
Reviewed-on: https://github.com/flang-compiler/f18/pull/219
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-10-18 13:03:51 -07:00
parent 84ea49d062
commit d804c9d6bb
8 changed files with 71 additions and 107 deletions

View File

@ -41,5 +41,24 @@ std::optional<int> ActualArgument::VectorSize() const {
return std::nullopt;
}
std::ostream &ProcedureRef::Dump(std::ostream &o) const {
proc_.Dump(o);
char separator{'('};
for (const auto &arg : arguments_) {
arg->Dump(o << separator);
separator = ',';
}
if (separator == '(') {
o << '(';
}
return o << ')';
}
Expr<SubscriptInteger> ProcedureRef::LEN() const {
// TODO: the results of the intrinsic functions REPEAT and TRIM have
// unpredictable lengths; maybe the concept of LEN() has to become dynamic
return proc_.LEN();
}
FOR_EACH_SPECIFIC_TYPE(template struct FunctionRef)
}

View File

@ -19,10 +19,15 @@
#include "type.h"
#include "../common/indirection.h"
#include "../parser/char-block.h"
#include "../semantics/attr.h"
#include <optional>
#include <ostream>
#include <vector>
namespace Fortran::semantics {
class Symbol;
}
namespace Fortran::evaluate {
struct ActualArgument {
@ -37,7 +42,9 @@ struct ActualArgument {
std::optional<parser::CharBlock> keyword;
bool isAssumedRank{false}; // TODO: make into a function of the value
bool isAlternateReturn{false};
bool isAlternateReturn{false}; // when true, "value" is a label number
// TODO: Mark legacy %VAL and %REF arguments
// Subtlety: There is a distinction that must be maintained here between an
// actual argument expression that is a variable and one that is not,
@ -48,5 +55,38 @@ struct ActualArgument {
};
using ActualArguments = std::vector<std::optional<ActualArgument>>;
// Intrinsics are identified by their names and the characteristics
// of their arguments, at least for now.
using IntrinsicProcedure = const char *; // not an owning pointer
struct SpecificIntrinsic {
explicit SpecificIntrinsic(IntrinsicProcedure n) : name{n} {}
SpecificIntrinsic(IntrinsicProcedure n, std::optional<DynamicType> &&dt,
int r, semantics::Attrs a)
: name{n}, type{std::move(dt)}, rank{r}, attrs{a} {}
std::ostream &Dump(std::ostream &) const;
IntrinsicProcedure name;
bool isRestrictedSpecific{false}; // if true, can only call it
std::optional<DynamicType> type; // absent if and only if subroutine call
int rank{0};
semantics::Attrs attrs; // ELEMENTAL, POINTER
};
struct ProcedureDesignator {
EVALUATE_UNION_CLASS_BOILERPLATE(ProcedureDesignator)
explicit ProcedureDesignator(SpecificIntrinsic &&i) : u{std::move(i)} {}
explicit ProcedureDesignator(const semantics::Symbol &n) : u{&n} {}
std::optional<DynamicType> GetType() const;
int Rank() const;
bool IsElemental() const;
Expr<SubscriptInteger> LEN() const;
const semantics::Symbol *GetSymbol() const;
std::ostream &Dump(std::ostream &) const;
// TODO: When calling X%F, pass X as PASS argument unless NOPASS
std::variant<SpecificIntrinsic, const semantics::Symbol *> u;
};
}
#endif // FORTRAN_EVALUATE_CALL_H_

View File

@ -655,9 +655,6 @@ public:
private:
using Others = std::variant<BOZLiteralConstant>;
// TODO pmk: Consider creating the union over the specifically typed
// Expr<> instances rather than the category unions. This would
// be a big refactor and slow down compiles but would simplify usage.
using Categories = common::MapTemplate<Expr, SomeCategory>;
public:

View File

@ -16,41 +16,19 @@
#define FORTRAN_EVALUATE_INTRINSICS_H_
#include "call.h"
#include "type.h"
#include "../common/idioms.h"
#include "../parser/char-block.h"
#include "../parser/message.h"
#include "../semantics/attr.h"
#include "../semantics/default-kinds.h"
#include <memory>
#include <optional>
#include <ostream>
#include <vector>
namespace Fortran::evaluate {
// Intrinsics are distinguished by their names and the characteristics
// of their arguments, at least for now.
using IntrinsicProcedure = const char *; // not an owning pointer
struct CallCharacteristics {
parser::CharBlock name;
bool isSubroutineCall{false};
};
struct SpecificIntrinsic {
explicit SpecificIntrinsic(IntrinsicProcedure n) : name{n} {}
SpecificIntrinsic(IntrinsicProcedure n, std::optional<DynamicType> &&dt,
int r, semantics::Attrs a)
: name{n}, type{std::move(dt)}, rank{r}, attrs{a} {}
std::ostream &Dump(std::ostream &) const;
IntrinsicProcedure name;
bool isRestrictedSpecific{false}; // if true, can only call it
std::optional<DynamicType> type; // absent if and only if subroutine call
int rank{0};
semantics::Attrs attrs; // ELEMENTAL, POINTER
};
struct SpecificCall {
SpecificCall(SpecificIntrinsic &&si, ActualArguments &&as)
: specificIntrinsic{std::move(si)}, arguments{std::move(as)} {}

View File

@ -298,36 +298,6 @@ std::ostream &ProcedureDesignator::Dump(std::ostream &o) const {
return Emit(o, u);
}
std::ostream &UntypedFunctionRef::Dump(std::ostream &o) const {
Emit(o, proc_);
char separator{'('};
for (const auto &arg : arguments_) {
Emit(o << separator, arg);
separator = ',';
}
if (separator == '(') {
o << '(';
}
return o << ')';
}
std::ostream &SubroutineCall::Dump(std::ostream &o) const {
Emit(o, proc_);
char separator{'('};
for (const auto &arg : arguments_) {
Emit(o << separator, arg);
separator = ',';
}
if (separator == '(') {
o << '(';
}
return o << ')';
}
std::ostream &Label::Dump(std::ostream &o) const {
return o << '*' << std::dec << label;
}
// LEN()
static Expr<SubscriptInteger> SymbolLEN(const Symbol &sym) {
return AsExpr(Constant<SubscriptInteger>{0}); // TODO
@ -370,11 +340,6 @@ Expr<SubscriptInteger> ProcedureDesignator::LEN() const {
}},
u);
}
Expr<SubscriptInteger> UntypedFunctionRef::LEN() const {
// TODO: the results of the intrinsic functions REPEAT and TRIM have
// unpredictable lengths; maybe the concept of LEN() has to become dynamic
return proc_.LEN();
}
// Rank()
int Component::Rank() const {

View File

@ -23,7 +23,6 @@
#include "call.h"
#include "common.h"
#include "intrinsics.h"
#include "type.h"
#include "../common/idioms.h"
#include "../lib/common/template.h"
@ -285,24 +284,10 @@ public:
FOR_EACH_CHARACTER_KIND(extern template class Designator)
struct ProcedureDesignator {
EVALUATE_UNION_CLASS_BOILERPLATE(ProcedureDesignator)
explicit ProcedureDesignator(SpecificIntrinsic &&i) : u{std::move(i)} {}
explicit ProcedureDesignator(const Symbol &n) : u{&n} {}
std::optional<DynamicType> GetType() const;
int Rank() const;
bool IsElemental() const;
Expr<SubscriptInteger> LEN() const;
const Symbol *GetSymbol() const;
std::ostream &Dump(std::ostream &) const;
std::variant<SpecificIntrinsic, const Symbol *, Component> u;
};
class UntypedFunctionRef {
class ProcedureRef {
public:
CLASS_BOILERPLATE(UntypedFunctionRef)
UntypedFunctionRef(ProcedureDesignator &&p, ActualArguments &&a)
CLASS_BOILERPLATE(ProcedureRef)
ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a)
: proc_{std::move(p)}, arguments_(std::move(a)) {}
const ProcedureDesignator &proc() const { return proc_; }
@ -318,14 +303,15 @@ protected:
ActualArguments arguments_;
};
template<typename A> struct FunctionRef : public UntypedFunctionRef {
template<typename A> struct FunctionRef : public ProcedureRef {
using Result = A;
static_assert(Result::isSpecificIntrinsicType ||
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
CLASS_BOILERPLATE(FunctionRef)
FunctionRef(UntypedFunctionRef &&ufr) : UntypedFunctionRef{std::move(ufr)} {}
FunctionRef(ProcedureRef &&pr) : ProcedureRef{std::move(pr)} {}
FunctionRef(ProcedureDesignator &&p, ActualArguments &&a)
: UntypedFunctionRef{std::move(p), std::move(a)} {}
: ProcedureRef{std::move(p), std::move(a)} {}
std::optional<DynamicType> GetType() const {
if constexpr (std::is_same_v<Result, SomeDerived>) {
if (const Symbol * symbol{proc_.GetSymbol()}) {
@ -358,27 +344,5 @@ template<typename A> struct Variable {
}
std::variant<Designator<Result>, FunctionRef<Result>> u;
};
struct Label { // TODO: this is a placeholder
CLASS_BOILERPLATE(Label)
explicit Label(int lab) : label{lab} {}
int label;
std::ostream &Dump(std::ostream &) const;
};
class SubroutineCall {
public:
CLASS_BOILERPLATE(SubroutineCall)
SubroutineCall(ProcedureDesignator &&p, ActualArguments &&a)
: proc_{std::move(p)}, arguments_(std::move(a)) {}
const ProcedureDesignator &proc() const { return proc_; }
const ActualArguments &arguments() const { return arguments_; }
int Rank() const { return 0; } // TODO: elemental subroutine representation
std::ostream &Dump(std::ostream &) const;
private:
ProcedureDesignator proc_;
ActualArguments arguments_;
};
}
#endif // FORTRAN_EVALUATE_VARIABLE_H_

View File

@ -915,8 +915,8 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::FunctionReference &funcRef) {
std::get<parser::ProcedureDesignator>(funcRef.v.t), arguments)}) {
if (std::optional<DynamicType> dyType{
proc->procedureDesignator.GetType()}) {
return TypedWrapper<FunctionRef, UntypedFunctionRef>(std::move(*dyType),
UntypedFunctionRef{std::move(proc->procedureDesignator),
return TypedWrapper<FunctionRef, ProcedureRef>(std::move(*dyType),
ProcedureRef{std::move(proc->procedureDesignator),
std::move(proc->arguments)});
}
}

View File

@ -17,6 +17,7 @@
#include "default-kinds.h"
#include "../evaluate/expression.h"
#include "../evaluate/intrinsics.h"
#include "../evaluate/type.h"
#include "../parser/parse-tree.h"
#include <optional>