forked from OSchip/llvm-project
[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:
parent
84ea49d062
commit
d804c9d6bb
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)} {}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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)});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue