From d9c0568075afeb6bcada422c1f8ae73efdcdb6b7 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Wed, 8 Aug 2018 14:52:38 +0200
Subject: [PATCH] macroprocessor: introduce Cartesion product. #5

---
 src/macro/MacroValue.cc | 61 +++++++++++++++++++++++++++++++++++++++++
 src/macro/MacroValue.hh |  2 ++
 2 files changed, 63 insertions(+)

diff --git a/src/macro/MacroValue.cc b/src/macro/MacroValue.cc
index 28484663..73695d94 100644
--- a/src/macro/MacroValue.cc
+++ b/src/macro/MacroValue.cc
@@ -428,6 +428,67 @@ ArrayMV::minus(const MacroValuePtr &mv) noexcept(false)
   return make_shared<ArrayMV>(new_values);
 }
 
+MacroValuePtr
+ArrayMV::times(const MacroValuePtr &mv) noexcept(false)
+{
+  auto mv2 = dynamic_pointer_cast<ArrayMV>(mv);
+  if (!mv2)
+    throw TypeError("Type mismatch for operands of * operator");
+
+  vector<MacroValuePtr> new_values;
+  for (auto &itl : values)
+    for (auto &itr : mv2->values)
+      {
+        vector<MacroValuePtr> new_tuple;
+        auto lmvi = dynamic_pointer_cast<IntMV>(itl);
+        if (lmvi)
+          new_tuple.push_back(lmvi);
+        else
+          {
+            auto lmvs = dynamic_pointer_cast<StringMV>(itl);
+            if (lmvs)
+              new_tuple.push_back(lmvs);
+            else
+              {
+                auto lmvt = dynamic_pointer_cast<TupleMV>(itl);
+                if (lmvt)
+                  new_tuple = lmvt->values;
+                else
+                  {
+                    cerr << "ArrayMV::times: unsupported type on lhs" << endl;
+                    exit(EXIT_FAILURE);
+                  }
+              }
+          }
+
+        auto rmvi = dynamic_pointer_cast<IntMV>(itr);
+        if (rmvi)
+          new_tuple.push_back(rmvi);
+        else
+          {
+            auto rmvs = dynamic_pointer_cast<StringMV>(itr);
+            if (rmvs)
+              new_tuple.push_back(rmvs);
+            else
+              {
+                auto rmvt = dynamic_pointer_cast<TupleMV>(itr);
+                if (rmvt)
+                  for (auto &tit : rmvt->values)
+                    new_tuple.push_back(tit);
+                 else
+                  {
+                    cerr << "ArrayMV::times: unsupported type on rhs" << endl;
+                    exit(EXIT_FAILURE);
+                  }
+              }
+          }
+
+        new_values.push_back(make_shared<TupleMV>(new_tuple));
+      }
+
+  return make_shared<ArrayMV>(new_values);
+}
+
 shared_ptr<IntMV>
 ArrayMV::is_equal(const MacroValuePtr &mv)
 {
diff --git a/src/macro/MacroValue.hh b/src/macro/MacroValue.hh
index 810d48d0..5e35292f 100644
--- a/src/macro/MacroValue.hh
+++ b/src/macro/MacroValue.hh
@@ -216,6 +216,8 @@ public:
   static shared_ptr<ArrayMV> range(const MacroValuePtr &mv1, const MacroValuePtr &mv2) noexcept(false);
   shared_ptr<ArrayMV> set_union(const MacroValuePtr &mvp) noexcept(false) override;
   shared_ptr<ArrayMV> set_intersection(const MacroValuePtr &mvp) noexcept(false) override;
+  // Computes the Cartesian product of two sets
+  MacroValuePtr times(const MacroValuePtr &mv) noexcept(false) override;
 };
 
 //! Represents a tuple value in macro language
-- 
GitLab