From d9ade1311788dc619b84f1ee2c0ec21827563cc2 Mon Sep 17 00:00:00 2001
From: Marius Bozga <Marius.Bozga@univ-grenoble-alpes.fr>
Date: Wed, 31 Mar 2021 16:24:10 +0200
Subject: [PATCH] Merge from IF2-B-Open:- allows for negative bounds in range
 types- implement the length operator for array types- fix type checking of
 call and conditional expressions

---
 src/code/type.m4       |  6 ++++++
 src/model/expression.C | 36 ++++++++++++++++++------------------
 src/model/expression.h |  4 ++--
 src/model/if.yacc.y    | 13 +++++++++++--
 4 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/src/code/type.m4 b/src/code/type.m4
index 0d6fea8..b5c6e17 100644
--- a/src/code/type.m4
+++ b/src/code/type.m4
@@ -309,6 +309,8 @@ inline void print_func($1)
     (const type_name($1) x, FILE* f);
 inline void reset_func($1)
     (type_name($1)& x);
+inline int if_$1_length
+    (const type_name($1) x);
 `#define' iterate_func($1)(x)\
 array_iterate($2,decr($4))')
 
@@ -348,6 +350,10 @@ inline void reset_func($1)
     (type_name($1)& x) {
   for(int i=0;i<$3;i++)
     reset_func($2)(x[i]);
+}
+inline int if_$1_length
+    (const type_name($1)) {
+  return $3;
 }')
 
 
diff --git a/src/model/expression.C b/src/model/expression.C
index e0f4559..b5c3353 100644
--- a/src/model/expression.C
+++ b/src/model/expression.C
@@ -331,7 +331,7 @@ void IfCallExpression::PreCompile() {
       IfType* type = entity->GetTypes()->Find(m_pName);
       if (type != NULL) {
         m_eOperator = CONSTRUCTOR;
-        if (Match(type))
+        if (Fulfil(type))
           m_pType = type;
         else
           Protest("type mismatch");
@@ -349,7 +349,7 @@ void IfCallExpression::PreCompile() {
           IfAbstractType* abstract = (IfAbstractType*) type;
           for(int i = 0; i < abstract->GetFunctions()->GetCount(); i++) {
             IfFunction* function = abstract->GetFunctions()->GetAt(i);
-            if (MatchFunc(function)) {
+            if (Fulfil(function)) {
               if (m_pType == NULL) {
                 m_eOperator = FUNCTION;
                 m_pFunction = function;
@@ -364,43 +364,43 @@ void IfCallExpression::PreCompile() {
     }
 }
 
-int IfCallExpression::Match(const IfType* type) {
-  int match = 0;
+int IfCallExpression::Fulfil(const IfType* type) {
+  int fulfil = 0;
   
   if (type->IsString()) {
     IfStringType* string = (IfStringType*) type;
     if (m_pParameters->GetCount() == 0)
-      match = 1;
+      fulfil = 1;
     if (m_pParameters->GetCount() == 1) {
       IfType* ptype =  m_pParameters->GetAt(0)->GetType();
       IfType* etype = string->GetElement();
-      match = ptype->Match(etype);
+      fulfil = ptype->Match(etype);
     }
   }
   
   if (type->IsRecord()) {
     IfRecordType* record = (IfRecordType*) type;
-    match = m_pParameters->GetCount() == record->GetFields()->GetCount();
-    for(int i = 0; i < m_pParameters->GetCount() && match; i++) {
+    fulfil = m_pParameters->GetCount() == record->GetFields()->GetCount();
+    for(int i = 0; i < m_pParameters->GetCount() && fulfil; i++) {
       IfType* ptype = m_pParameters->GetAt(i)->GetType();
       IfType* ftype = record->GetFields()->GetAt(i)->GetType();
-      match &= ptype->Match(ftype);
+      fulfil &= ptype->Match(ftype);
     }
   }
   
-  return match;
+  return fulfil;
 } 
 
-int IfCallExpression::MatchFunc(const IfFunction* function) {
-  int match = 
+int IfCallExpression::Fulfil(const IfFunction* function) {
+  int fulfil = 
     m_pParameters->GetCount() == function->GetParameters()->GetCount();
-  for(int i = 0; i < m_pParameters->GetCount() && match; i++) {
+  for(int i = 0; i < m_pParameters->GetCount() && fulfil; i++) {
     IfType* ptype = m_pParameters->GetAt(i)->GetType();
     IfType* ftype = function->GetParameters()->GetAt(i);
-    match &= ptype->Match(ftype);
+    fulfil &= ptype->Match(ftype);
   }
-  match &= strcmp(m_pName, function->GetName()) == 0;
-  return match;
+  fulfil &= strcmp(m_pName, function->GetName()) == 0;
+  return fulfil;
 }
 
 void IfCallExpression::Code(FILE* file) const {
@@ -1114,7 +1114,7 @@ void IfUnaryExpression::PreCompile() {
         m_pType = (m_eOperator == ACTIVE) ? boolean : integer;
       break;
     case LENGTH:
-      if (tr->IsString())
+      if (tr->IsArray() || tr->IsString())
         m_pType = integer;
       break;
     case PLUS: case MINUS:
@@ -1372,7 +1372,7 @@ void IfTernaryExpression::PreCompile() {
     switch (m_eOperator) {
     case CONDITIONAL:
       if (m_pTop->GetType()->Match(boolean) &&
-          m_pLeft->GetType() == m_pRight->GetType())
+          m_pLeft->GetType()->Match(m_pRight->GetType()))
         m_pType = m_pLeft->GetType();
       break;
     case SUBSTRING:
diff --git a/src/model/expression.h b/src/model/expression.h
index 04c8305..7c4079b 100644
--- a/src/model/expression.h
+++ b/src/model/expression.h
@@ -243,8 +243,8 @@ class IfCallExpression : public IfExpression {
   virtual int Use(const IfVariable* Variable) const;
   
  protected:
-  virtual int Match(const IfType* Type);
-  virtual int MatchFunc(const IfFunction* Function);
+  int Fulfil(const IfType* Type);
+  int Fulfil(const IfFunction* Function);
   
  public:
   static Operator OPERATOR[];
diff --git a/src/model/if.yacc.y b/src/model/if.yacc.y
index b356d82..e055253 100644
--- a/src/model/if.yacc.y
+++ b/src/model/if.yacc.y
@@ -211,7 +211,7 @@ void yywarning(const char* msg) {
   float probability;
 }
 
-%type <constant> constant constant_decl constant_body constant_value
+%type <constant> constant constant_decl constant_body constant_value range_bound
 
 %type <literal> enum_decl  
 %type <literal_list> enum_decl_list
@@ -418,7 +418,7 @@ type_body :
 type_value :
   ENUM_K enum_decl_list ENDENUM_K 
     { $$ = new IfEnumType($2, NULL); } 
-| RANGE_K constant_body DDOT_K constant_body 
+| RANGE_K range_bound DDOT_K range_bound 
     { $$ = new IfRangeType($2, $4, NULL); }
 | RECORD_K field_decl_set ENDRECORD_K 
     { $$ = new IfRecordType($2, NULL); }
@@ -456,6 +456,15 @@ type_list :
 --------------------------------------------------------------------
 */
 
+range_bound :
+  constant_body { $$ = $1; }
+| '-' integer { $$ = new IfIntegerConstant(-$2, NULL); }
+;
+
+/*
+--------------------------------------------------------------------
+*/
+
 enum_decl :
   constant_name { $$ = new IfEnumConstant($1); }
 ;
-- 
GitLab