equivalence.c

     
   1  //! @file equivalence.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-2024 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  //! Compile EQUIVALENCE statements.
  25  
  26  #include <vif.h>
  27  
  28  static void eq_var_var_slice (EXPR lhs, EXPR rhs, int_4 *N)
  29  {
  30    IDENT *lid = lhs.idf, *rid = rhs.idf; RECORD str;
  31    if (lid->equiv != NULL) {
  32      if (rid->equiv == NULL) {
  33        eq_var_var_slice (rhs, lhs, N);
  34      } else {
  35       _srecordf (str, "(%s, %s)", FID (lid), FID (rid));
  36       ERROR (1201, "equivalence", str);
  37      }
  38    } else if (rid->common != LOCAL) {
  39      cpp_direct (nprocs, prelin, REFDECL);
  40      _srecordf (str, "static %s %s = %s &(%s);\n", wtype (&lhs.mode, NOARG, NOFUN), ptr_to_array (lhs.idf, CONST, NOCAST, ACTUAL), ptr_to_array (lhs.idf, NOCONST, CAST, ACTUAL), rhs.str);
  41      code (nprocs, REFDECL, str);
  42      lid->const_ref = TRUE;
  43    } else if (lhs.mode.save == STATIC) {
  44      if (rhs.mode.save == STATIC) {
  45        cpp_direct (nprocs, prelin, REFDECL);
  46        _srecordf (str, "static %s %s = %s &(%s);\n", wtype (&lhs.mode, NOARG, NOFUN), ptr_to_array (lhs.idf, CONST, NOCAST, ACTUAL), ptr_to_array (lhs.idf, NOCONST, CAST, ACTUAL), rhs.str);
  47        code (nprocs, REFDECL, str);
  48        lid->const_ref = TRUE;
  49      } else {
  50        cpp_direct (nprocs, prelin, EQUIV);
  51        _srecordf (str, "%s = %s &(%s);\n", lhs.str, ptr_to_array (lhs.idf, NOCONST, CAST, ACTUAL), rhs.str);
  52        code (nprocs, EQUIV, str);
  53        N++;
  54      }
  55    } else {
  56      cpp_direct (nprocs, prelin, BODY);
  57      _srecordf (str, "%s = %s &(%s);\n", lhs.str, ptr_to_array (lhs.idf, NOCONST, CAST, ACTUAL), rhs.str);
  58      code (nprocs, BODY, str);
  59    }
  60  }
  61  
  62  static void eq_slice_slice (EXPR lhs, EXPR rhs, int_4 *N)
  63  {
  64    IDENT *lid = lhs.idf, *rid = rhs.idf; RECORD str;
  65    if (rid->common != LOCAL) {
  66      cpp_direct (nprocs, prelin, DECL);
  67      _srecordf (str, "static %s %s = %s &(%s);\n", wtype (&lhs.mode, NOARG, NOFUN), ptr_to_array (lid, CONST, NOCAST, ACTUAL), ptr_to_array (lid, NOCONST, CAST, ACTUAL), rhs.str);
  68      code (nprocs, DECL, str);
  69      lid->const_ref = TRUE;
  70    } else {
  71      _srecordf (str, "%s = %s &(%s);\n", CID (lid), ptr_to_array (lid, NOCONST, CAST, ACTUAL), rhs.str);
  72      if (lhs.mode.save == STATIC) {
  73        cpp_direct (nprocs, prelin, EQUIV);
  74        code (nprocs, EQUIV, str);
  75        N++;
  76      } else {
  77        cpp_direct (nprocs, prelin, BODY);
  78        code (nprocs, BODY, str);
  79      }
  80    }
  81  }
  82  
  83  static void eq_link (EXPR lhs, EXPR rhs, int_4 *N)
  84  {
  85    IDENT *lid = lhs.idf, *rid = rhs.idf;
  86    if (lid == NULL || rid == NULL) {
  87      ERROR (1202, "equivalence", "arguments");
  88      return;
  89    }
  90  // ROW -> VAR is VAR -> ROW.
  91    if (lid->mode.dim != 0 && rid->mode.dim == 0) {
  92      eq_link (rhs, lhs, N);
  93      return;
  94    }
  95  // Shuffle when needed.
  96    if (lid->equiv != NULL) {
  97      if (rid->equiv == NULL) {
  98        eq_link (rhs, lhs, N);
  99        return;
 100      } else {
 101        RECORD str;
 102        _srecordf (str, "(%s, %s)", FID (lid), FID (rid));
 103        ERROR (1203, "equivalence", str);
 104      }
 105    }
 106    lid->alias = rid;
 107    rid->equiv = lid;
 108  // VAR -> VAR is OK.
 109    if (lid->mode.dim == 0 && rid->mode.dim == 0) {
 110      eq_var_var_slice (lhs, rhs, N);
 111    }
 112  // VAR -> ROW is OK.
 113    if (lid->mode.dim == 0 && rid->mode.dim != 0) {
 114      eq_var_var_slice (lhs, rhs, N);
 115    }
 116  // ROW -> ROW is sometimes OK. This is a VIF limitation.
 117    if (lid->mode.dim != 0 && rid->mode.dim != 0) {
 118      if (!lhs.base_elem) {
 119        SYNTAX (1204, "restricted to first array element");
 120        return;
 121      }
 122      eq_slice_slice (lhs, rhs, N);
 123    }
 124  }
 125  
 126  void equivalence (void)
 127  {
 128  // EQUIVALENCE is limited to making aliases to already allocated
 129  // variables or arrays (which is the common application anyway).
 130  //
 131    int_4 rc, N = 0;
 132    int_4 epatch = code (nprocs, EQUIV, NULL);
 133    while ((rc = scan (NULL)) != END_OF_LINE) {
 134      if (TOKEN (",")) {
 135        continue;
 136      } else if (TOKEN ("(")) {
 137        continue;
 138      } else if (rc != WORD) {
 139        SYNTAX (1205, NULL);
 140      } else {
 141        IDENT *lid, *rid;
 142        EXPR lhs, rhs;
 143        MODE lmode, rmode;
 144        lid = impl_decl (curlex, &lmode);
 145        if (lid->alias != NULL) {
 146          ERROR (1206, "multiple equivalencing", curlex);
 147        }
 148        factor (&lhs);
 149        rc = scan (NULL);
 150        if (!TOKEN (",")) {
 151          EXPECT (1207, ",");
 152        }
 153        rc = scan (NULL);
 154        if (rc != WORD) {
 155          EXPECT (1208, "variable");
 156        }
 157        rid = impl_decl (curlex, &rmode);
 158        factor (&rhs);
 159        rc = scan (NULL);
 160  // Mistakes.
 161        if (lid->mode.save != rid->mode.save) {
 162          ERROR (1209, "aliasing static and automatic", NULL);
 163          continue;
 164        }
 165        if (lid->common != LOCAL && rid->common != LOCAL) {
 166          ERROR (1210, "both elements are common", NULL);
 167          continue;
 168        }
 169  // If a row is denoted as variable, address of first element is implied.
 170  // Padding "[0]" simplifies code generation.
 171        if (lhs.variant == EXPR_VAR && lid->mode.dim != 0) {
 172          bufcat (lhs.str, "[0]", RECLN);
 173          lhs.base_elem = TRUE;
 174        }
 175        if (rhs.variant == EXPR_VAR && rid->mode.dim != 0) {
 176          bufcat (rhs.str, "[0]", RECLN);
 177          rhs.base_elem = TRUE;
 178        }
 179  // Equivalence in correct order.
 180        if (lid->common == LOCAL) {
 181          eq_link (lhs, rhs, &N);
 182        } else if (rid->common == LOCAL) {
 183          eq_link (rhs, lhs, &N);
 184        } else {
 185          eq_link (lhs, rhs, &N);
 186        } 
 187      }
 188    }
 189    if (N > 0) {
 190      RECORD str;
 191      cpp_direct (nprocs, prelin, EQUIV);
 192      _srecordf (str, "if (__calls[%d].calls == 0) {\n", nprocs - 1);
 193      patch (epatch, str);
 194      code (nprocs, EQUIV, "}\n");
 195    }
 196  }
 197  
 198  void decl_equiv (void)
 199  {
 200    int_4 go_on = TRUE;
 201    while (go_on) {
 202      SAVE_POS;
 203      int_4 rc = scan (NULL);
 204      if (rc == DECLAR) {
 205        skip_card ();
 206      } else if (TOKEN ("implicit")) {
 207        skip_card ();
 208      } else if (TOKEN ("save")) {
 209        skip_card ();
 210      } else if (TOKEN ("automatic")) {
 211        skip_card ();
 212      } else if (TOKEN ("parameter")) {
 213        skip_card ();
 214      } else if (TOKEN ("common")) {
 215        skip_card ();
 216      } else if (TOKEN ("dimension")) {
 217        skip_card ();
 218      } else if (TOKEN ("equivalence")) {
 219        equivalence ();
 220        skip_card ();
 221      } else if (TOKEN ("external")) {
 222        skip_card ();
 223      } else if (TOKEN ("intrinsic")) {
 224        skip_card ();
 225      } else if (TOKEN ("data")) {
 226        skip_card ();
 227      } else if (strlen (curlex) > 0) {
 228  // Backspace and done.
 229        RESTORE_POS;
 230        go_on = FALSE;
 231      }
 232    }
 233  }
     


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