From 2b1eedd132c2086e1418f137d601369d14a9ec9c Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Fri, 2 Aug 2019 16:56:01 -0400
Subject: [PATCH] macro processor: introduce tuple casts

---
 src/macro/Expressions.cc                 |  8 ++++++++
 src/macro/Expressions.hh                 | 15 +++++++++++++++
 src/macro/ForwardDeclarationsAndEnums.hh |  1 +
 src/macro/Parser.yy                      |  6 ++++--
 src/macro/Tokenizer.ll                   |  1 +
 5 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc
index f2121200..696f4e33 100644
--- a/src/macro/Expressions.cc
+++ b/src/macro/Expressions.cc
@@ -773,6 +773,8 @@ UnaryOp::eval()
           return argbt->cast_double();
         case codes::UnaryOp::cast_string:
           return argbt->cast_string();
+        case codes::UnaryOp::cast_tuple:
+          return argbt->cast_tuple();
         case codes::UnaryOp::logical_not:
           return argbt->logical_not();
         case codes::UnaryOp::unary_minus:
@@ -1099,6 +1101,8 @@ UnaryOp::to_string() const noexcept
       return "(double)" + retval;
     case codes::UnaryOp::cast_string:
       return "(string)" + retval;
+    case codes::UnaryOp::cast_tuple:
+      return "(tuple)" + retval;
     case codes::UnaryOp::logical_not:
       return "!" + retval;
     case codes::UnaryOp::unary_minus:
@@ -1308,6 +1312,9 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept
     case codes::UnaryOp::cast_string:
       output << "(string)";
       break;
+    case codes::UnaryOp::cast_tuple:
+      output << "(tuple)";
+      break;
     case codes::UnaryOp::logical_not:
       output << "!";
       break;
@@ -1396,6 +1403,7 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept
   if (op_code != codes::UnaryOp::cast_int
       && op_code != codes::UnaryOp::cast_double
       && op_code != codes::UnaryOp::cast_string
+      && op_code != codes::UnaryOp::cast_tuple
       && op_code != codes::UnaryOp::logical_not
       && op_code != codes::UnaryOp::unary_plus
       && op_code != codes::UnaryOp::unary_minus)
diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh
index 2dde31f4..61f2d4ab 100644
--- a/src/macro/Expressions.hh
+++ b/src/macro/Expressions.hh
@@ -183,6 +183,7 @@ namespace macro
     virtual DoublePtr cast_int() const { throw StackTrace("This type cannot be cast to an integer"); }
     virtual DoublePtr cast_double() const { throw StackTrace("This type cannot be cast to a double"); }
     virtual StringPtr cast_string() const { throw StackTrace("This type cannot be cast to a string"); }
+    virtual TuplePtr cast_tuple() const { throw StackTrace("This type cannot be cast to a tuple"); }
   };
 
 
@@ -208,6 +209,10 @@ namespace macro
     inline DoublePtr cast_int() const override { return value ? make_shared<Double>(1, env) : make_shared<Double>(0, env); }
     inline DoublePtr cast_double() const override { return cast_int(); }
     inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
+    inline TuplePtr cast_tuple() const override
+    {
+      return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Bool>(value, env)}, env);
+    }
   };
 
 
@@ -295,6 +300,10 @@ namespace macro
     inline DoublePtr cast_int() const override { return make_shared<Double>(static_cast<int>(value), env); }
     inline DoublePtr cast_double() const override { return make_shared<Double>(value, env); }
     inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
+    inline TuplePtr cast_tuple() const override
+    {
+      return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Double>(value, env)}, env);
+    }
   };
 
   class String final : public BaseType
@@ -322,6 +331,10 @@ namespace macro
     inline DoublePtr cast_int() const override;
     inline DoublePtr cast_double() const override;
     inline StringPtr cast_string() const override { return make_shared<String>(value, env); }
+    inline TuplePtr cast_tuple() const override
+    {
+      return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<String>(value, env)}, env);
+    }
   };
 
 
@@ -350,6 +363,7 @@ namespace macro
     DoublePtr cast_int() const override;
     DoublePtr cast_double() const override;
     inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
+    inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(tup, env); }
   };
 
 
@@ -394,6 +408,7 @@ namespace macro
     DoublePtr cast_int() const override;
     DoublePtr cast_double() const override;
     inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
+    inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(arr, env); }
   };
 
 
diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh
index a0baa757..2fce6fe8 100644
--- a/src/macro/ForwardDeclarationsAndEnums.hh
+++ b/src/macro/ForwardDeclarationsAndEnums.hh
@@ -70,6 +70,7 @@ namespace macro
        cast_int,
        cast_double,
        cast_string,
+       cast_tuple,
        logical_not,
        unary_minus,
        unary_plus,
diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy
index 51d8384a..12b46230 100644
--- a/src/macro/Parser.yy
+++ b/src/macro/Parser.yy
@@ -65,7 +65,7 @@ using namespace macro;
 %token SQRT CBRT SIGN MAX MIN FLOOR CEIL TRUNC SUM MOD
 %token ERF ERFC GAMMA LGAMMA ROUND NORMPDF NORMCDF LENGTH
 
-%token INT DOUBLE STRING
+%token INT DOUBLE STRING TUPLE
 
 %left OR
 %left AND
@@ -78,7 +78,7 @@ using namespace macro;
 %left PLUS MINUS
 %left TIMES DIVIDE
 %precedence UMINUS UPLUS NOT
-%precedence CAST_INT CAST_DOUBLE CAST_STRING
+%precedence CAST_INT CAST_DOUBLE CAST_STRING CAST_TUPLE
 %nonassoc POWER
 
 %token <string> NAME TEXT QUOTED_STRING NUMBER EOL
@@ -328,6 +328,8 @@ expr : LPAREN expr RPAREN
        { $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_double, $4, driver.env, @$); }
      | LPAREN STRING RPAREN expr %prec CAST_STRING
        { $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_string, $4, driver.env, @$); }
+     | LPAREN TUPLE RPAREN expr %prec CAST_TUPLE
+       { $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_tuple, $4, driver.env, @$); }
      | NOT expr
        { $$ = make_shared<UnaryOp>(codes::UnaryOp::logical_not, $2, driver.env, @$); }
      | MINUS expr %prec UMINUS
diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll
index 6f4b78d0..e072e3cd 100644
--- a/src/macro/Tokenizer.ll
+++ b/src/macro/Tokenizer.ll
@@ -145,6 +145,7 @@ CONT \\\\{SPC}*
 <expr,eval>int             { return token::INT; }
 <expr,eval>double          { return token::DOUBLE; }
 <expr,eval>string          { return token::STRING; }
+<expr,eval>tuple           { return token::TUPLE; }
 
 <expr,eval>((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+([ed][-+]?[0-9]+)?)|nan|inf {
   yylval->build<string>(yytext);
-- 
GitLab