[flang] Add analyzed assignment to parse tree
authorTim Keith <tkeith@nvidia.com>
Sat, 23 Nov 2019 00:04:56 +0000 (16:04 -0800)
committerTim Keith <tkeith@nvidia.com>
Tue, 26 Nov 2019 19:19:04 +0000 (11:19 -0800)
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

flang/lib/evaluate/expression.cc
flang/lib/evaluate/expression.h
flang/lib/parser/parse-tree.cc
flang/lib/parser/parse-tree.h
flang/lib/semantics/tools.cc
flang/lib/semantics/tools.h
flang/tools/f18/stub-evaluate.cc

index 47a8f3b..98bee95 100644 (file)
@@ -175,6 +175,8 @@ bool GenericExprWrapper::operator==(const GenericExprWrapper &that) const {
   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; },
@@ -194,3 +196,4 @@ std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
 INSTANTIATE_EXPRESSION_TEMPLATES
 }
 DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
+DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
index 6a2fe18..5456e66 100644 (file)
@@ -854,6 +854,21 @@ public:
   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.
@@ -864,6 +879,13 @@ struct GenericExprWrapper {
   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, )
index 7cdad21..7788185 100644 (file)
@@ -23,6 +23,9 @@ namespace Fortran::evaluate {
 struct GenericExprWrapper {
   ~GenericExprWrapper();
 };
+struct GenericAssignmentWrapper {
+  ~GenericAssignmentWrapper();
+};
 }
 
 namespace Fortran::parser {
@@ -248,3 +251,4 @@ std::ostream &operator<<(std::ostream &os, const Name &x) {
 }
 
 template class std::unique_ptr<Fortran::evaluate::GenericExprWrapper>;
+template class std::unique_ptr<Fortran::evaluate::GenericAssignmentWrapper>;
index 5d4b10b..a2708f4 100644 (file)
@@ -70,6 +70,7 @@ class DerivedTypeSpec;
 // 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
@@ -1918,6 +1919,9 @@ struct DeallocateStmt {
 // 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;
 };
 
index 04ab228..0868d74 100644 (file)
@@ -315,6 +315,11 @@ bool ExprTypeKindIsDefault(
       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{
index 5d886c9..7f38608 100644 (file)
@@ -241,6 +241,8 @@ template<typename T> const SomeExpr *GetExpr(const T &x) {
   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);
index 0460415..980e4ef 100644 (file)
@@ -24,6 +24,11 @@ struct GenericExprWrapper {
   ~GenericExprWrapper();
 };
 GenericExprWrapper::~GenericExprWrapper() = default;
+struct GenericAssignmentWrapper {
+  ~GenericAssignmentWrapper();
+};
+GenericAssignmentWrapper::~GenericAssignmentWrapper() = default;
 }
 
 DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
+DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)