coerce.c

     1  //! @file coerce.c
     2  //! @author J. Marcel van der Veer
     3  //
     4  //! @section Copyright
     5  //
     6  // This file is part of VIF - vintage FORTRAN compiler.
     7  // Copyright 2020-2025 J. Marcel van der Veer <algol68g@xs4all.nl>.
     8  //
     9  //! @section License
    10  //
    11  // This program is free software; you can redistribute it and/or modify it 
    12  // under the terms of the GNU General Public License as published by the 
    13  // Free Software Foundation; either version 3 of the License, or 
    14  // (at your option) any later version.
    15  //
    16  // This program is distributed in the hope that it will be useful, but 
    17  // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
    18  // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
    19  // more details. You should have received a copy of the GNU General Public 
    20  // License along with this program. If not, see <http://www.gnu.org/licenses/>.
    21  
    22  //! @section Synopsis
    23  //!
    24  //! Type conversions for assignments and function statements.
    25  
    26  #include <vif.h>
    27  
    28  logical_4 coerce (EXPR * lhs, EXPR * rhs)
    29  {
    30  // Sensible defaults.
    31    RECCPY (lhs->str, rhs->str);
    32  // Oftentimes, no action is required.
    33    if (lhs->mode.type == rhs->mode.type && lhs->mode.len == rhs->mode.len) {
    34      return TRUE;
    35    }
    36  // Warn for possible precision loss.
    37    if (lhs->mode.type == REAL && rhs->mode.type == REAL) {
    38      if (lhs->mode.len < rhs->mode.len) {
    39        PRECISION_LOSS (601, qtype (&(rhs->mode)), qtype (&(lhs->mode)));
    40      }
    41    }
    42    if (lhs->mode.type == COMPLEX && rhs->mode.type == COMPLEX) {
    43      if (lhs->mode.len < rhs->mode.len) {
    44        PRECISION_LOSS (602, qtype (&(rhs->mode)), qtype (&(lhs->mode)));
    45      }
    46    }
    47    if (lhs->mode.type == COMPLEX && rhs->mode.type == REAL) {
    48      if (lhs->mode.len < 2 * rhs->mode.len) {
    49        PRECISION_LOSS (603, qtype (&(rhs->mode)), qtype (&(lhs->mode)));
    50      }
    51    }
    52    if (lhs->mode.type == REAL && rhs->mode.type == COMPLEX) {
    53      if (2 * lhs->mode.len < rhs->mode.len) {
    54        PRECISION_LOSS (604, qtype (&(rhs->mode)), qtype (&(lhs->mode)));
    55      }
    56    }
    57  // Insert coercions.
    58    if (lhs->mode.type == REAL && lhs->mode.len == 32) {
    59      if (rhs->mode.type == REAL) {
    60        switch (rhs->mode.len) {
    61          case 4: _srecordf (lhs->str, "flttox (%s)", rhs->str); break;
    62          case 8: _srecordf (lhs->str, "dbltox (%s)", rhs->str); break;
    63          case 16: _srecordf (lhs->str, "quadtox (%s)", rhs->str); break;
    64        }
    65        return TRUE;
    66      } else if (rhs->mode.type == INTEGER) {
    67        switch (rhs->mode.len) {
    68          case 2: _srecordf (lhs->str, "inttox (%s)", rhs->str); break;
    69          case 4: _srecordf (lhs->str, "inttox (%s)", rhs->str); break;
    70          case 8: _srecordf (lhs->str, "quadtox (%s)", rhs->str); break;
    71        }
    72        return TRUE;
    73      } else {
    74        return FALSE;
    75      }
    76    } else if (lhs->mode.type == COMPLEX && lhs->mode.len == 64) {
    77      if (rhs->mode.type == COMPLEX) {
    78        switch (rhs->mode.len) {
    79          case 8: _srecordf (lhs->str, "cxflt (%s)", rhs->str); break;
    80          case 16: _srecordf (lhs->str, "cxdbl (%s)", rhs->str); break;
    81          case 32: _srecordf (lhs->str, "cxquad (%s)", rhs->str); break;
    82        }
    83        return TRUE;
    84      } else if (rhs->mode.type == REAL) {
    85        switch (rhs->mode.len) {
    86          case 4: _srecordf (lhs->str, "cxdbl (CMPLX (%s, 0.0))", rhs->str); break;
    87          case 8: _srecordf (lhs->str, "cxdbl (CMPLX (%s, 0.0))", rhs->str); break;
    88          case 16: _srecordf (lhs->str, "cxquad (CMPLXQ (%s, 0.0q))", rhs->str); break;
    89          case 32: _srecordf (lhs->str, "cxreal32 (%s)", rhs->str); break;
    90        }
    91        return TRUE;
    92      } else if (rhs->mode.type == INTEGER) {
    93        switch (rhs->mode.len) {
    94          case 2: _srecordf (lhs->str, "%s = cxdbl (CMPLX (%s, 0.0))", rhs->str); break;
    95          case 4: _srecordf (lhs->str, "%s = cxdbl (CMPLX (%s, 0.0))", rhs->str); break;
    96          case 8: _srecordf (lhs->str, "%s = cxquad (CMPLXQ (%s, 0.0q))", rhs->str); break;
    97        }
    98        return TRUE;
    99      } else {
   100        return FALSE;
   101      }
   102    } else if (rhs->mode.type == REAL && rhs->mode.len == 32) {
   103      if (lhs->mode.type == COMPLEX) {
   104        switch (lhs->mode.len) {
   105          case 8: _srecordf (lhs->str, "xtoflt (%s)", rhs->str); break;
   106          case 16: _srecordf (lhs->str, "xtodbl (%s)", rhs->str); break;
   107          case 32: _srecordf (lhs->str, "xtoquad (%s)", rhs->str); break;
   108        }
   109        return TRUE;
   110      } else if (lhs->mode.type == REAL) {
   111        switch (lhs->mode.len) {
   112          case 4: _srecordf (lhs->str, "xtoflt (%s)", rhs->str); break;
   113          case 8: _srecordf (lhs->str, "xtodbl (%s)", rhs->str); break;
   114          case 16: _srecordf (lhs->str, "xtoquad (%s)", rhs->str); break;
   115        }
   116        return TRUE;
   117      } else if (lhs->mode.type == INTEGER) {
   118        switch (lhs->mode.len) {
   119          case 2: _srecordf (lhs->str, "(int_2) _xint8 (%s)", rhs->str); break;
   120          case 4: _srecordf (lhs->str, "(int_4) _xint8 (%s)", rhs->str); break;
   121          case 8: _srecordf (lhs->str, "_xint8 (%s)", rhs->str); break;
   122        }
   123        return TRUE;
   124      } else {
   125        return FALSE;
   126      }
   127    } else if (rhs->mode.type == COMPLEX && rhs->mode.len == 64) {
   128      if (lhs->mode.type == COMPLEX) {
   129        switch (lhs->mode.len) {
   130          case 8: _srecordf (lhs->str, "CMPLX (xtodbl (cxreal (%s)), xtodbl (cximag (%s)))", rhs->str, rhs->str); break;
   131          case 16: _srecordf (lhs->str, "CMPLX (xtodbl (cxreal (%s)), xtodbl (cximag (%s)))", rhs->str, rhs->str); break;
   132          case 32: _srecordf (lhs->str, "CMPLXQ (xtoquad (cxreal (%s)), xtoquad (cximag (%s)))", rhs->str, rhs->str); break;
   133        }
   134        return TRUE;
   135      } else if (lhs->mode.type == REAL) {
   136        switch (lhs->mode.len) {
   137          case 4: _srecordf (lhs->str, "xtoflt (cxreal (%s))", rhs->str); break;
   138          case 8: _srecordf (lhs->str, "xtodbl (cxreal (%s))", rhs->str); break;
   139          case 16: _srecordf (lhs->str, "xtoquad (cxreal (%s))", rhs->str); break;
   140        }
   141        return TRUE;
   142      } else if (lhs->mode.type == INTEGER) {
   143        switch (lhs->mode.len) {
   144          case 2: _srecordf (lhs->str, "(int_2) _xint8 (cxreal (%s))", rhs->str); break;
   145          case 4: _srecordf (lhs->str, "(int_4) _xint8 (cxreal (%s))", rhs->str); break;
   146          case 8: _srecordf (lhs->str, "_xint8 (cxreal (%s))", rhs->str); break;
   147        }
   148        return TRUE;
   149      } else {
   150        return FALSE;
   151      }
   152    } else if (rhs->mode.type == COMPLEX && rhs->mode.len == 32) {
   153      if (lhs->mode.type == COMPLEX) {
   154        switch (lhs->mode.len) {
   155          case 64: _srecordf (lhs->str, "CMPLXX (xtoquad (crealq (%s)), xtoquad (cimagq (%s)))", rhs->str, rhs->str); break;
   156        }
   157        return TRUE;
   158      } else if (lhs->mode.type == REAL) {
   159        switch (lhs->mode.len) {
   160          case 4: _srecordf (lhs->str, "(real_4) (crealq (%s))", rhs->str); break;
   161          case 8: _srecordf (lhs->str, "(real_8) (crealq (%s))", rhs->str); break;
   162          case 16: _srecordf (lhs->str, "crealq (%s)", rhs->str); break;
   163        }
   164        return TRUE;
   165      } else if (lhs->mode.type == INTEGER) {
   166        switch (lhs->mode.len) {
   167          case 2: _srecordf (lhs->str, "(int_2) (crealq (%s))", rhs->str); break;
   168          case 4: _srecordf (lhs->str, "(int_4) (crealq (%s))", rhs->str); break;
   169          case 8: _srecordf (lhs->str, "(int_8) (crealq (%s))", rhs->str); break;
   170        }
   171        return TRUE;
   172      } else {
   173        return FALSE;
   174      }
   175    } else if (rhs->mode.type == COMPLEX && rhs->mode.len == 16) {
   176      if (lhs->mode.type == COMPLEX) {
   177        switch (lhs->mode.len) {
   178          case 64: _srecordf (lhs->str, "CMPLXX (_xtodbl (creal (%s)), _xtodbl (cimag (%s)))", rhs->str, rhs->str); break;
   179        }
   180        return TRUE;
   181      } else if (lhs->mode.type == REAL) {
   182        switch (lhs->mode.len) {
   183          case 4: _srecordf (lhs->str, "(real_4) (creal (%s))", rhs->str); break;
   184          case 8: _srecordf (lhs->str, "(real_8) (creal (%s))", rhs->str); break;
   185          case 16: _srecordf (lhs->str, "creal (%s)", rhs->str); break;
   186        }
   187        return TRUE;
   188      } else if (lhs->mode.type == INTEGER) {
   189        switch (lhs->mode.len) {
   190          case 2: _srecordf (lhs->str, "(int_2) (creal (%s))", rhs->str); break;
   191          case 4: _srecordf (lhs->str, "(int_4) (creal (%s))", rhs->str); break;
   192          case 8: _srecordf (lhs->str, "(int_8) (creal (%s))", rhs->str); break;
   193        }
   194        return TRUE;
   195      } else {
   196        return FALSE;
   197      }
   198    } else if (rhs->mode.type == COMPLEX && rhs->mode.len == 8) {
   199      if (lhs->mode.type == COMPLEX) {
   200        switch (lhs->mode.len) {
   201          case 64: _srecordf (lhs->str, "CMPLXX (_xtoflt (crealf (%s)), _xtoflt (cimagf (%s)))", rhs->str, rhs->str); break;
   202        }
   203        return TRUE;
   204      } else if (lhs->mode.type == REAL) {
   205        switch (lhs->mode.len) {
   206          case 4: _srecordf (lhs->str, "(real_4) (crealf (%s))", rhs->str); break;
   207          case 8: _srecordf (lhs->str, "(real_8) (crealf (%s))", rhs->str); break;
   208          case 16: _srecordf (lhs->str, "(real_16) (crealf (%s))", rhs->str); break;
   209        }
   210        return TRUE;
   211      } else if (lhs->mode.type == INTEGER) {
   212        switch (lhs->mode.len) {
   213          case 2: _srecordf (lhs->str, "(int_2) (crealf (%s))", rhs->str); break;
   214          case 4: _srecordf (lhs->str, "(int_4) (crealf (%s))", rhs->str); break;
   215          case 8: _srecordf (lhs->str, "(int_8) (crealf (%s))", rhs->str); break;
   216        }
   217        return TRUE;
   218      } else {
   219        return FALSE;
   220      }
   221    } else if (lhs->mode.type == INTEGER && lhs->mode.len == 4 && rhs->mode.type == CHARACTER) {
   222      _srecordf (lhs->str, "_str_to_int4 (%s)", rhs->str);
   223      return TRUE;
   224    } else if (lhs->mode.type == REAL && lhs->mode.len == 8 && rhs->mode.type == CHARACTER) {
   225      _srecordf (lhs->str, "_str_to_real8 (%s)", rhs->str);
   226      return TRUE;
   227    } 
   228    return TRUE; // Assume no action required.
   229  }


© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)