Add `typedAssignment` to the `AssignmentStmt` node, analagous to
`typedExpr` in `Expr`. This represents the analyzed form of an assignment.
It may be a subroutine call in the case of a user-defined assignment.
Add `GetAssignment` function to get it from the parse tree node if present.
Original-commit: flang-compiler/f18@
675b0b9bb7617231e8e4bfa0c7a63423c74d79a4
Reviewed-on: https://github.com/flang-compiler/f18/pull/841
Tree-same-pre-rewrite: false
return v == that.v;
}
+GenericAssignmentWrapper::~GenericAssignmentWrapper() = default;
+
template<TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
return std::visit(
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
INSTANTIATE_EXPRESSION_TEMPLATES
}
DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
+DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
common::CombineVariants<TypelessExpression, CategoryExpression> u;
};
+// An assignment is either intrinsic (with lhs and rhs) or user-defined,
+// represented as a ProcedureRef.
+class Assignment {
+public:
+ explicit Assignment(ProcedureRef &&x) : u{std::move(x)} {}
+ Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
+ : u{IntrinsicAssignment{std::move(lhs), std::move(rhs)}} {}
+ struct IntrinsicAssignment {
+ Expr<SomeType> lhs;
+ Expr<SomeType> rhs;
+ };
+
+ std::variant<IntrinsicAssignment, ProcedureRef> u;
+};
+
// This wrapper class is used, by means of a forward reference with
// an owning pointer, to cache analyzed expressions in parse tree nodes.
// v is nullopt if an error occurred during expression analysis.
std::optional<Expr<SomeType>> v;
};
+// Like GenericExprWrapper but for analyzed assignments
+struct GenericAssignmentWrapper {
+ GenericAssignmentWrapper(std::optional<Assignment> &&x) : v{std::move(x)} {}
+ ~GenericAssignmentWrapper();
+ std::optional<Assignment> v;
+};
+
FOR_EACH_CATEGORY_TYPE(extern template class Expr, )
FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, )
FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues, )
struct GenericExprWrapper {
~GenericExprWrapper();
};
+struct GenericAssignmentWrapper {
+ ~GenericAssignmentWrapper();
+};
}
namespace Fortran::parser {
}
template class std::unique_ptr<Fortran::evaluate::GenericExprWrapper>;
+template class std::unique_ptr<Fortran::evaluate::GenericAssignmentWrapper>;
// type-checked generic expression representations by semantic analysis.
namespace Fortran::evaluate {
struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
+struct GenericAssignmentWrapper; // forward definition, represent assignment
}
// Most non-template classes in this file use these default definitions
// R1032 assignment-stmt -> variable = expr
struct AssignmentStmt {
TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
+ using TypedAssignment = std::unique_ptr<evaluate::GenericAssignmentWrapper,
+ common::Deleter<evaluate::GenericAssignmentWrapper>>;
+ mutable TypedAssignment typedAssignment;
std::tuple<Variable, Expr> t;
};
dynamicType->kind() == context.GetDefaultKind(dynamicType->category());
}
+const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &x) {
+ const auto &typed{x.typedAssignment};
+ return typed && typed->v ? &*typed->v : nullptr;
+}
+
const Symbol *FindInterface(const Symbol &symbol) {
return std::visit(
common::visitors{
return GetExprHelper{}.Get(x);
}
+const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &);
+
template<typename T> std::optional<std::int64_t> GetIntValue(const T &x) {
if (const auto *expr{GetExpr(x)}) {
return evaluate::ToInt64(*expr);
~GenericExprWrapper();
};
GenericExprWrapper::~GenericExprWrapper() = default;
+struct GenericAssignmentWrapper {
+ ~GenericAssignmentWrapper();
+};
+GenericAssignmentWrapper::~GenericAssignmentWrapper() = default;
}
DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
+DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)