factor.c

     1  //! @file factor.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  //! Compile Fortran expression factors.
    25  
    26  #include <vif.h>
    27  
    28  static void implicit_name (EXPR *loc, IDENT *idf, MODE *mode, RECORD name)
    29  {
    30    UNSCAN;
    31    idf = impl_decl (name, mode);
    32    if (idf != NO_IDENT && idf->mode.type == NOTYPE && idf->external == FALSE) {
    33      ERROR (1601, "variable has no type", C_NAME (idf));
    34    }
    35    _srecordf (loc->str, "%s", C_NAME (idf));
    36    loc->variant = EXPR_VAR;
    37    loc->idf = idf;
    38    loc->mode = idf->mode;
    39  }
    40  
    41  void factor_variable (EXPR *loc, IDENT *idf, MODE *mode, RECORD name)
    42  {
    43    if (idf == NO_IDENT) {
    44      idf = impl_decl (name, mode);
    45    }
    46    if (idf == NO_IDENT) {
    47      BUG ("cannot store identifier");
    48    }
    49    if (idf->mode.type == NOTYPE && idf->external == FALSE) {
    50      ERROR (1602, "variable has no type", FTN_NAME (idf));
    51    }
    52    if (idf->arg || idf->alias != NO_IDENT) {
    53      if (IS_ROW (idf->mode) || idf->mode.type == CHARACTER) {
    54        _srecordf (loc->str, "%s", C_NAME (idf), RECLN);
    55      } else {
    56        _srecordf (loc->str, "(*%s)", C_NAME (idf), RECLN);
    57      }
    58    } else {
    59      if (NOT_LOCAL (idf)) {
    60        (void) idf_full_c_name (loc->str, idf);
    61      } else if (idf->nest > 0) {
    62        NEW_RECORD (res);
    63        _srecordf (res, "%s", edit_vn (C_NAME (idf), idf->nest));
    64        bufcat (loc->str, res, RECLN);
    65      } else {
    66        bufcat (loc->str, C_NAME (idf), RECLN);
    67      }
    68    }
    69    loc->variant = EXPR_VAR;
    70    loc->idf = idf;
    71    loc->mode = idf->mode;
    72  }
    73  
    74  void factor_integer_number (EXPR *loc, char *str)
    75  {
    76  // We let length depend on the denotation.
    77    int_8 val = strtoll (str, NO_REF_TEXT, 10);
    78    loc->variant = EXPR_CONST;
    79    if (val >= SHRT_MIN && val <= SHRT_MAX) {
    80      _srecordf (loc->str, "%s", str);
    81      loc->mode = (MODE) {.type = INTEGER, .len = 2, .dim = 0};
    82    } else if (val >= INT_MIN && val <= INT_MAX) {
    83      _srecordf (loc->str, "%s", str);
    84      loc->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
    85    } else if (val >= LLONG_MIN && val <= LLONG_MAX) {
    86      _srecordf (loc->str, "%s", str);
    87      loc->mode = (MODE) {.type = INTEGER, .len = 8, .dim = 0};
    88    } else {
    89      FATAL (1603, INTERNAL_CONSISTENCY, NO_TEXT);
    90    }
    91  }
    92  
    93  static void factor_real_number (EXPR *loc)
    94  {
    95    char *expo;
    96    NEW_RECORD (edit);
    97    RECCPY (edit, curlex);
    98    if ((expo = strchr (edit, 'e')) != NO_TEXT || (expo = strchr (edit, 'E')) != NO_TEXT) {
    99      loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
   100      _srecordf (loc->str, "%s", pretty_float (edit));
   101    } else if ((expo = strchr (edit, 'd')) != NO_TEXT || (expo = strchr (edit, 'D')) != NO_TEXT) {
   102      *expo = 'e';
   103      loc->mode = (MODE) {.type = REAL, .len = 8, .dim = 0};
   104      _srecordf (loc->str, "%s", pretty_float (edit));
   105    } else if ((expo = strchr (edit, 'q')) != NO_TEXT || (expo = strchr (edit, 'Q')) != NO_TEXT) {
   106      *expo = 'e';
   107      loc->mode = (MODE) {.type = REAL, .len = 16, .dim = 0};
   108      _srecordf (loc->str, "%sq", pretty_float (edit));
   109    } else if ((expo = strchr (edit, 'x')) != NO_TEXT || (expo = strchr (edit, 'X')) != NO_TEXT) {
   110      *expo = 'e';
   111      loc->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
   112      _srecordf (loc->str, "_dc_%d", code_real_32_const (pretty_float (edit)));
   113    } else {
   114  // No exponent.
   115      loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
   116      _srecordf (loc->str, "%s", pretty_float (edit));
   117    }
   118    loc->variant = EXPR_CONST;
   119  }
   120  
   121  static void factor_complex_number (EXPR *loc, EXPR lhs)
   122  {
   123    (void) scan (EXPECT_NONE);
   124    EXPR rhs;
   125    memset (&rhs, 0, sizeof (rhs));
   126    express (&rhs, NOTYPE, 0);
   127    int_4 len = mix_len (&lhs, &rhs);
   128    if (len == 32) {
   129      _srecordf (loc->str, "CMPLXX (%s, %s)", lhs.str, rhs.str);
   130      loc->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
   131    } else if (len == 16) {
   132      _srecordf (loc->str, "CMPLXQ (%s, %s)", lhs.str, rhs.str);
   133      loc->mode = (MODE) {.type = COMPLEX, .len = 32, .dim = 0};
   134    } else if (len == 8) {
   135      _srecordf (loc->str, "CMPLX (%s, %s)", lhs.str, rhs.str);
   136      loc->mode = (MODE) {.type = COMPLEX, .len = 16, .dim = 0};
   137    } else {
   138      _srecordf (loc->str, "CMPLXF (%s, %s)", lhs.str, rhs.str);
   139      loc->mode = (MODE) {.type = COMPLEX, .len = 8, .dim = 0};
   140    }
   141    if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
   142      loc->variant = EXPR_CONST;
   143    }
   144    (void) scan (EXPECT_NONE);
   145  }
   146  
   147  void factor (EXPR * reg)
   148  {
   149    int_4 rc;
   150    MODE mode;
   151    EXPR loc;
   152    NEW_RECORD (name);
   153    bufcpy (name, curlex, RECLN);
   154    memset (&loc, 0, sizeof (EXPR));
   155    loc.variant = EXPR_OTHER;
   156    if (curret == WORD || curret == DECLAR) { 
   157      IDENT *idf = find_local (name, &mode);
   158      logical_4 pack = lookahead ("(");
   159      if (curret == DECLAR && pack) {
   160        // Some intrinsics share name with a declarer, like REAL (I).
   161        intrinsic_call (name, &loc);
   162        memcpy (reg, &loc, sizeof (EXPR));
   163        return;
   164      }
   165      if (idf != NO_IDENT && idf->intrinsic && !pack) {
   166        // Intrinsic function as parameter must be 'specific'.
   167        // Otherwise ambiguity results -> implementation dependent result.
   168        // implicit dcos
   169        // call zeroin (dcos, ...)
   170        if (!is_specific (name)) {
   171          EXPECT (1604, "generic intrinsic subprogram name");
   172        }
   173        reg->idf = idf;
   174        _srecordf (reg->str, "%s", edit_i (name));
   175        reg->variant = EXPR_VAR;
   176        return;
   177      }
   178      if (idf != NO_IDENT && idf->intrinsic && pack) {
   179        // intrinsic dcos
   180        // ... dcos (x) 
   181        rc = scan (EXPECT_NONE);
   182        if (TOKEN ("(")) {
   183          factor_function_call (&loc, name);
   184        }
   185        memcpy (reg, &loc, sizeof (EXPR));
   186        (void) rc;
   187        return;
   188      }
   189      if (! (idf != NO_IDENT && idf->external)) {
   190        // Not a call to a declared external name.
   191        logical_4 int_call = FALSE;
   192        if (idf != NO_IDENT && idf->intrinsic && pack) {
   193          int_call = intrinsic_call (name, &loc);
   194        } else if (idf == NO_IDENT) {
   195          int_call = intrinsic_call (name, &loc);
   196        }
   197        if (int_call) {
   198          memcpy (reg, &loc, sizeof (EXPR));
   199          return;
   200        } 
   201      }
   202      if (idf != NO_IDENT && idf->mode.dim == 0 && !idf->intrinsic && !idf->external && pack) {
   203        // Name is declared but not as intrinsic or external.
   204        // In VIF this gives a check on function return type.
   205        // real*8 cos
   206        // y = cos (1.0d0)
   207        if (is_intrins (name, NO_MODE)) {
   208          if (intrinsic_call (name, &loc)) {
   209            if (!accept_mode (loc.mode.type, loc.mode.len, idf->mode.type, idf->mode.len)) {
   210              MODE_ERROR (1605, qtype (&(loc.mode)), qtype (&(idf->mode)));
   211            }
   212            memcpy (reg, &loc, sizeof (EXPR));
   213            return;
   214          }
   215        }
   216      }
   217      if (idf == NO_IDENT || idf->external) {
   218        // Undefined locally can mean function call.
   219        // In VIF, 'external' always means you supply the routine.
   220        // external cos
   221        // call zeroin (cos, ...)
   222        rc = scan (EXPECT_NONE);
   223        if (TOKEN ("(")) {
   224          factor_function_call (&loc, name);
   225        } else {
   226          implicit_name (&loc, idf, &mode, name);
   227        }
   228        memcpy (reg, &loc, sizeof (EXPR));
   229        (void) rc;
   230        return;
   231      }
   232      // 
   233      if (pack) {
   234        rc = scan (EXPECT_NONE);
   235        idf = impl_decl (name, &mode);
   236        if (idf->mode.type == CHARACTER) {
   237          factor_slice_char (&loc, idf);
   238          if (idf->parm) {
   239            loc.mode = idf->mode;
   240            loc.variant = EXPR_CONST;
   241          }
   242        } else if (IS_SCALAR (idf->mode)) {
   243          if (strcmp (name, modnam) == 0) {
   244            recursion (&loc, modnam, idf);
   245          } else if (idf->source == MACRO) {
   246            macro (&loc, idf);
   247          } else {
   248            factor_function_call (&loc, name);
   249          }
   250        } else {
   251          // Row slice.
   252          factor_slice (&loc, idf);
   253        }
   254      } else {
   255        if (idf->parm) {
   256          bufcat (loc.str, idf->parm, RECLN);
   257          loc.mode = idf->mode;
   258          loc.variant = EXPR_CONST;
   259        } else {
   260          idf = impl_decl (name, &mode);
   261          factor_variable (&loc, idf, &mode, name);
   262        }
   263      }
   264      memcpy (reg, &loc, sizeof (EXPR));
   265      return;
   266    } else if (TOKEN ("+")) {
   267  // + factor.
   268      EXPR fac;
   269      memset (&fac, 0, sizeof (EXPR));
   270      rc = scan (EXPECT_NONE);
   271      factor (&fac);
   272      if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
   273        EXPECT (1606, "arithmetical expression");
   274      }
   275      _srecordf (loc.str, "%s", fac.str);
   276      loc.mode = fac.mode;
   277      if (fac.variant == EXPR_CONST) {
   278        loc.variant = EXPR_CONST;
   279      } else {
   280        loc.variant = EXPR_OTHER;
   281      }
   282    } else if (TOKEN ("-")) {
   283  // - factor.
   284      EXPR fac;
   285      memset (&fac, 0, sizeof (EXPR));
   286      rc = scan (EXPECT_NONE);
   287      factor (&fac);
   288      if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
   289        EXPECT (1607, "arithmetical expression");
   290      }
   291      if (fac.mode.type == COMPLEX && fac.mode.len == 64) {
   292        _srecordf (loc.str, "cxneg (%s)", fac.str);
   293      } else if (fac.mode.type == REAL && fac.mode.len == 32) {
   294        _srecordf (loc.str, "xneg (%s)", fac.str);
   295      } else {
   296        _srecordf (loc.str, "-%s", fac.str);
   297      }
   298      loc.mode = fac.mode;
   299      if (fac.variant == EXPR_CONST) {
   300        loc.variant = EXPR_CONST;
   301      } else {
   302        loc.variant = EXPR_OTHER;
   303      }
   304    } else if (TOKEN (".true.") || TOKEN (".t.")) {
   305  // LOGICAL constant TRUE.
   306      _srecordf (loc.str, "TRUE");
   307      loc.mode = (MODE) {
   308      .type = LOGICAL, .len = 4, .dim = 0};
   309      loc.variant = EXPR_CONST;
   310    } else if (TOKEN (".false.") || TOKEN (".f.")) {
   311  // LOGICAL constant FALSE.
   312      _srecordf (loc.str, "FALSE");
   313      loc.mode = (MODE) {
   314      .type = LOGICAL, .len = 4, .dim = 0};
   315      loc.variant = EXPR_CONST;
   316    } else if (curret == INT_NUMBER) {
   317  // INTEGER constant.
   318      factor_integer_number (&loc, curlex);
   319      MAXIMISE (loc.mode.len, 4);
   320    } else if (curret == FLT_NUMBER) {
   321  // REAL constnat.
   322      factor_real_number (&loc);
   323    } else if (curret == TEXT) {
   324  // TEXT constant.
   325      NEW_RECORD (idf);
   326      _srecordf (idf, "_dc_%d", code_uniq_str (curlex));
   327      _srecordf (loc.str, "%s", idf);
   328      int len = strlen (curlex) - 2;
   329      if (len < 1) {
   330        len = 1;
   331      }
   332      loc.mode = (MODE) {.type = CHARACTER, .len = len, .dim = 0};
   333      norm_mode (&loc.mode);
   334      loc.variant = EXPR_CONST;
   335    } else if (TOKEN ("(")) {
   336      EXPR lhs;
   337      memset (&lhs, 0, sizeof (lhs));
   338      rc = scan (EXPECT_NONE);
   339      express (&lhs, NOTYPE, 0);
   340      rc = scan (EXPECT_NONE);
   341      if (TOKEN (",")) {
   342  // COMPLEX number.
   343        factor_complex_number (&loc, lhs);
   344      } else {
   345  // Parenthesized expression.
   346        if (lhs.variant == EXPR_CONST) {
   347          loc.variant = EXPR_CONST;
   348          _srecordf (loc.str, "%s", lhs.str);
   349        } else {
   350          loc.variant = EXPR_OTHER;
   351          _srecordf (loc.str, "(%s)", lhs.str);
   352        }
   353        loc.mode = lhs.mode;
   354      }
   355      CHECKPOINT (1608, ")");
   356    } else {
   357      ERROR (1609, "expected operand", NO_TEXT);
   358      loc.mode.type = ETYPE;
   359    }
   360    memcpy (reg, &loc, sizeof (EXPR));
   361    (void) rc;
   362  }


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