Polaris: Expression.cc Source File

Expression.cc

Go to the documentation of this file.
00001 ///
00002 /// \file Expression.cc
00003 ///
00004 /// Expression - related code:  Expression class and all derived classes
00005 ///
00006 ///
00007 #ifdef POLARIS_GNU_PRAGMAS
00008 #pragma implementation "expr_funcs.h"
00009 #pragma implementation "Expression.h"
00010 ///
00011 #pragma implementation "StringExpr.h"
00012 #pragma implementation "UnaryExpr.h"
00013 #pragma implementation "BinaryExpr.h"
00014 #pragma implementation "NonBinaryExpr.h"
00015 ///
00016 #pragma implementation "ArgNumberExpr.h"
00017 #pragma implementation "ArrayRefExpr.h"
00018 #pragma implementation "CommaExpr.h"
00019 #pragma implementation "ComplexExpr.h"
00020 #pragma implementation "DoExpr.h"
00021 #pragma implementation "EqualExpr.h"
00022 #pragma implementation "FormatExpr.h"
00023 #pragma implementation "FunctionCallExpr.h"
00024 #pragma implementation "HollerithConstExpr.h"
00025 #pragma implementation "IDExpr.h"
00026 #pragma implementation "IOStarExpr.h"
00027 #pragma implementation "InfinityExpr.h"
00028 #pragma implementation "IntConstExpr.h"
00029 #pragma implementation "IntrinsicCallExpr.h"
00030 #pragma implementation "KeyExpr.h"
00031 #pragma implementation "LabelExpr.h"
00032 #pragma implementation "LambdaCallExpr.h"
00033 #pragma implementation "LogicalConstExpr.h"
00034 #pragma implementation "OmegaExpr.h"
00035 #pragma implementation "GSAExpr.h"
00036 #pragma implementation "RealConstExpr.h"
00037 #pragma implementation "ReturnStarExpr.h"
00038 #pragma implementation "StmtLabelExpr.h"
00039 #pragma implementation "StringConstExpr.h"
00040 #pragma implementation "SubStringExpr.h"
00041 #pragma implementation "TableExpr.h"
00042 #pragma implementation "DistributeExpr.h"
00043 #endif
00044 ///
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <iostream.h>
00048 #include <ctype.h>
00049 #include <limits.h>
00050 #include <set>
00051 
00052 /// #include <math.h>
00053 extern "C" double   ceil(double);
00054 extern "C" double   floor(double);
00055 
00056 
00057 #include "../BinRep.h"
00058 #include "../debug.h"
00059 #include "../Collection/List.h"
00060 #include "../Collection/Iterator.h"
00061 #include "../Collection/Mutator.h"
00062 #include "../Collection/RefElement.h"
00063 #include "../Collection/RefSet.h"
00064 #include "../Directive/Directive.h"
00065 #include "../Permutation.h"
00066 #include "../String.h"
00067 #include "../Statement/Statement.h"
00068 #include "../Symtab.h"
00069 #include "../Symbol/VariableSymbol.h"
00070 #include "../Symbol/FunctionSymbol.h"
00071 #include "../Symbol/SubroutineSymbol.h"
00072 #include "../Type.h"
00073 #include "../ProgramUnit.h"
00074 #include "../VDL.h"
00075 #include "../utilities/expression_util.h"
00076 #include "../utilities/string_util.h"
00077 #include "../utilities/switches_util.h"
00078 #include "../utilities/symbol_util.h"
00079 
00080 #include "../p-assert.h"
00081 #include "../macros.h"
00082 #include "../rotate.h"
00083 
00084 #include "expr.h"
00085 
00086 #include "expr_funcs.h"
00087 #include "Expression.h"
00088 #include "replace.h"
00089 
00090 #include "StringExpr.h"
00091 #include "UnaryExpr.h"
00092 #include "BinaryExpr.h"
00093 #include "NonBinaryExpr.h"
00094 
00095 #include "ArgNumberExpr.h"
00096 #include "ArrayRefExpr.h"
00097 #include "CommaExpr.h"
00098 #include "ComplexExpr.h"
00099 #include "DoExpr.h"
00100 #include "EqualExpr.h"
00101 #include "FormatExpr.h"
00102 #include "FunctionCallExpr.h"
00103 #include "HollerithConstExpr.h"
00104 #include "IDExpr.h"
00105 #include "IOStarExpr.h"
00106 #include "InfinityExpr.h"
00107 #include "IntConstExpr.h"
00108 #include "IntrinsicCallExpr.h"
00109 #include "KeyExpr.h"
00110 #include "LabelExpr.h"
00111 #include "LambdaCallExpr.h"
00112 #include "LogicalConstExpr.h"
00113 #include "OmegaExpr.h"
00114 #include "GSAExpr.h"
00115 #include "RealConstExpr.h"
00116 #include "ReturnStarExpr.h"
00117 #include "StmtLabelExpr.h"
00118 #include "StringConstExpr.h"
00119 #include "SubStringExpr.h"
00120 #include "TableExpr.h"
00121 #include "DistributeExpr.h"
00122 
00123 #include "../Wildcard/Wildcard.all.h"
00124 
00125 #include "IntrinsicTable.h"
00126 
00127 
00128 static int subst_field_print = 0;
00129 
00130 //------------------------------------------------------------------------
00131 /// Expression base class code:
00132 ///
00133 
00134 static char    *op_string[NUM_OP_TYPES] = {
00135     "DELETED_EXPRESSION_OP",
00136     "INTEGER_CONSTANT_OP",
00137     "REAL_CONSTANT_OP",
00138     "STRING_CONSTANT_OP",
00139     "LOGICAL_CONSTANT_OP",
00140     "HOLLERITH_CONSTANT_OP",
00141     "COMPLEX_OP",
00142     "ARRAY_REF_OP",
00143     "SUBSTRING_OP",
00144     "FUNCTION_CALL_OP",
00145     "INTRINSIC_CALL_OP",
00146     "LAMBDA_CALL_OP",
00147     "ARG_OP",
00148     "RETURN_OP",
00149     "LABEL_OP",
00150     "IO_STAR_OP",
00151     "FORMAT_OP",
00152     "ID_OP",
00153     "U_PLUS_OP",
00154     "U_MINUS_OP",
00155     "NOT_OP",
00156     "EQ_OP",
00157     "NE_OP",
00158     "LT_OP",
00159     "LE_OP",
00160     "GT_OP",
00161     "GE_OP",
00162     "SUB_OP",
00163     "DIV_OP",
00164     "INTDIV_OP",
00165     "RATDIV_OP",
00166     "EXP_OP",
00167     "CONCAT_OP",
00168     "ADD_OP",
00169     "MULT_OP",
00170     "OR_OP",
00171     "AND_OP",
00172     "EQV_OP",
00173     "NEQV_OP",
00174     "DO_OP",
00175     "EQUAL_OP",
00176     "COMMA_OP",
00177     "COLON_OP",
00178     "PAREN_OP",
00179     "OMEGA_OP",
00180     "REPSTAR_OP",
00181 
00182     "TABLE_ENTRY",
00183     "STMT_LABEL_OP",
00184 
00185     "KEY_OP",
00186     "KEYPAIR_OP",
00187 
00188     "INFINITY_OP",
00189 
00190     "ALPHA_OP",
00191     "GAMMA_OP",
00192     "MU_OP",
00193     "THETA_OP",
00194     "ETA_OP",
00195 
00196     "DISTRIBUTE_OP",  /// ... _
00197  
00198     /// ...  Wild Card Types
00199     "ANY_EXPR_SUBSET_WC",
00200 
00201     "FORBOL_EXPR_WC",
00202     "FORBOL_STMT_WC",
00203     "FORBOL_EXPR_PMF_WC",
00204     "FORBOL_STMT_PMF_WC",
00205     "FORBOL_BLOCK_PMF_WC",
00206     
00207     "AND_WC",
00208     "OR_WC",
00209     "NOT_WC",
00210     "CONTAINS_WC",
00211     "SUCH_THAT_WC",
00212     "ANY_WC",
00213     "ANY_EXPR_OF_TYPE_WC",
00214     "ANY_CONST_WC",
00215     "ANY_INT_CONST_WC",
00216     "ANY_HOLLERITH_CONST_WC",
00217     "ANY_LOGICAL_CONST_WC",
00218     "ANY_REAL_CONST_WC",
00219     "ANY_STRING_CONST_WC",
00220     "ANY_ARRAY_REF_WC",
00221     "ANY_BINARY_WC",
00222     "ANY_COMMA_WC",
00223     "ANY_COMPLEX_WC",
00224     "ANY_ID_WC",
00225     "ANY_FUNCTION_CALL_WC",
00226     "ANY_INTRINSIC_CALL_WC",
00227     "ANY_NON_BINARY_WC",
00228     "ANY_SUBSTRING_WC",
00229     "ANY_UNARY_WC",
00230     "ANY_INT_WC",
00231     "ANY_REAL_WC"
00232 };
00233 
00234 void set_subst_field_print() {
00235     subst_field_print = 1;
00236 }
00237 
00238 Expression::~Expression() 
00239 {
00240     #ifdef CLASS_INSTANCE_REGISTRY
00241     unregister_instance(EXPRESSION, this);
00242     #endif
00243 
00244     if (_overflow) 
00245         delete _overflow;
00246     _overflow = 0;
00247     _op = DELETED_EXPRESSION_OP;
00248 }
00249 
00250 void
00251 Expression::_ref_error(const char *method) const
00252 {
00253     cerr << "***Error: Expression:  undefined method called:\n"
00254          << "Expression object of type "
00255          << op_string[op()] << " (number "
00256          << op() << ") called method  " << method << endl;
00257 
00258     p_abort("(See above error message)");
00259 }
00260 
00261 //------------------------------------------------------------------------ 
00262 
00263 Boolean
00264 is_commutative(OP_TYPE op)
00265 {
00266     switch (op) {
00267     case ADD_OP:
00268     case MULT_OP:
00269     case AND_OP:
00270     case OR_OP:
00271     case EQV_OP:
00272     case NEQV_OP:
00273         return True;
00274 
00275     default:
00276         return False;
00277     }
00278 }
00279 
00280 Boolean
00281 is_conjunctive_op(OP_TYPE op)
00282 {
00283     switch (op) {
00284     case AND_OP:
00285     case OR_OP:
00286     case EQV_OP:
00287     case NEQV_OP:
00288         return True;
00289 
00290     default:
00291         return False;
00292     }
00293 }
00294 
00295 Boolean
00296 is_relational_op(OP_TYPE op)
00297 {
00298     switch (op) {
00299     case EQ_OP:
00300     case NE_OP:
00301     case LT_OP:
00302     case LE_OP:
00303     case GT_OP:
00304     case GE_OP:
00305         return True;
00306 
00307     default:
00308         return False;
00309     }
00310 }
00311 
00312 
00313 /// Used only to act as a return value in cases where control flow cannot
00314 /// reach the end of a procedure (in order to avoid a compiler
00315 /// warning/error)
00316 
00317 #define DUMMY_EXPR_REF (*(Expression *)0)
00318 
00319 /// Declare the following Expression argument field as an alias to another
00320 /// field
00321 
00322 #define ALIAS_ARG(class, alias, alias_to)                                   \
00323     void class::alias(Expression *e) { alias_to(e); }                       \
00324     Expression &class::alias() const { return alias_to(); }                 \
00325     Boolean class::alias ## _valid() const { return alias_to ## _valid(); }
00326 
00327 
00328 #define ALIAS_ARG_ASSERT(class, alias, alias_to, req_op, msg)               \
00329     void class::alias(Expression *e) { p_assert(e->op() == req_op, msg);    \
00330                                        alias_to(e); }                       \
00331     Expression &class::alias() const { return alias_to(); }                 \
00332     Boolean class::alias ## _valid() const { return alias_to ## _valid(); }
00333 
00334 Boolean
00335 is_logical_false(const Expression & e)
00336 {
00337     return ((e.op() == LOGICAL_CONSTANT_OP) && (e.str_data() == ".FALSE."));
00338 }
00339 
00340 Boolean
00341 is_integer_zero(const Expression & e)
00342 {
00343     return (e.op() == INTEGER_CONSTANT_OP && e.value() == 0);
00344 }
00345 
00346 Boolean
00347 is_integer_one(const Expression & e)
00348 {
00349     return (e.op() == INTEGER_CONSTANT_OP && e.value() == 1);
00350 }
00351 
00352 Boolean
00353 is_integer_constant(const Expression & e)
00354 {
00355     return (e.op() == INTEGER_CONSTANT_OP);
00356 }
00357 
00358 Boolean
00359 is_integer_constant(const Expression & e, int val)
00360 {
00361     return (e.op() == INTEGER_CONSTANT_OP && e.value() == val);
00362 }
00363 
00364 bool
00365 is_phi_function(const Expression & e)
00366 {
00367     switch (e.op()) {
00368     case GAMMA_OP:
00369     case MU_OP:
00370     case THETA_OP:
00371     case ETA_OP:
00372     return true;
00373     default:
00374     return false;
00375     }
00376     return false;
00377 }
00378 
00379 bool
00380 is_pseudo_function(const Expression & e)
00381 {
00382     switch (e.op()) {
00383     case ALPHA_OP:
00384     case GAMMA_OP:
00385     case MU_OP:
00386     case THETA_OP:
00387     case ETA_OP:
00388     return true;
00389     case FUNCTION_CALL_OP:
00390     if (!strcmp(e.function().symbol().name_ref(), "<BETA>"))
00391         return true;
00392     default:
00393     return false;
00394     }
00395     return false;
00396 }
00397 
00398 /// Given a Fortran character constant enclosed in double quotes, convert
00399 ///   it into a character constant enclosed in single quotes (making all
00400 ///   necessary syntactic changes)
00401 /// The string returned must be deleted using  'delete []'
00402 /// Returns 0 if there was an error. (i.e. mismatched quotes, etc.)
00403 
00404 ////////////////////////////////////////////////////////////
00405 
00406 static char *
00407 double_to_single_quoted(const char *dbl) 
00408 {
00409     int dbl_len = strlen(dbl);
00410   
00411     /// ...  Need a workspace of a most 2*len(dbl) size
00412 
00413     char *work = new char[2*dbl_len + 1];
00414 
00415     work[0] = '\''; /// ...  First single quote
00416 
00417     /// ...  Now go through, changing single quotes to single quote pairs, and 
00418     /// ...  changing double quotes pairs to double quotes
00419 
00420     int work_i, dbl_i;
00421 
00422     for (work_i = 1, dbl_i = 1; dbl_i < dbl_len - 1; ++work_i, ++dbl_i) {
00423         /// ...  Everything between the outer quotes
00424 
00425         switch (dbl[dbl_i]) {
00426         case '\'': /// ...  Replace with pair
00427             work[work_i ++ ] = '\'';
00428             work[work_i] = '\'';
00429             break;
00430 
00431         case '"': /// ...  Replace pair with single
00432             if (dbl_i >= dbl_len - 2 || dbl[dbl_i + 1] != '"' ) {
00433                 delete work;
00434                 return 0; /// ...  This is not a double quote pair -- error
00435             }
00436             work[work_i] = '"';
00437             ++dbl_i; /// ...  Skip the extra in the pair
00438             break;
00439 
00440         default:
00441             work[work_i] = dbl[dbl_i];
00442             break;
00443         }
00444     }
00445 
00446     work[work_i] = '\''; /// ...  Last single quote
00447     work[work_i + 1] = '\000'; /// ...  NULL-terminate
00448 
00449     return work;
00450 }
00451 
00452 
00453 ////////////////////////////////////////////////////////////////
00454 /// These routines are used to propogate rank information from
00455 /// the symbol table to the Types of all Expressions.  These
00456 /// are called as part of the pre-pass.
00457 ////////////////////////////////////////////////////////////////
00458 
00459 /// Report an error in an intrinsic parameter
00460 
00461 void 
00462 report_param_error( Expression & expr, char *intrin, 
00463                     int param_num, char *expected)
00464 {
00465     cerr << "compute_intrinsic_type: Error found in intrinsic argument" 
00466          << endl;
00467     cerr << "Error found in the Expression " << expr 
00468          << ". The intrinsic " << intrin << " requires " 
00469          << expected << " type in parameter number " << param_num 
00470          << endl;
00471 
00472     p_abort("report_param_error: Parameter Error (see above)");
00473 }
00474 
00475 /// Compute the type of expr which is an IntrinsicCallExpr
00476 
00477 void 
00478 compute_intrinsic_type(Expression & expr)
00479 {
00480     IntrinsicTable tab;
00481 
00482     String intrin = expr.intrinsic().symbol().name_ref();
00483 
00484     int index = tab.lookup_intrinsic(intrin);
00485 
00486     /// ...  Check if parameter has been axed (what the hell does this mean?)
00487 
00488     if (tab.axed(index)) {
00489         cerr << "compute_intrinsic_type: Error in expression: " 
00490              << expr << endl;
00491         p_abort("Attempt to call 'axed' intrinsic");
00492     }
00493 
00494     /// ...  Make sure it does not require global special handling
00495 
00496     if (!tab.special(index)) {
00497         /// ...  Make sure there are some parameters
00498 
00499         if (!expr.parameters_valid()) {
00500             cerr << "compute_intrinsic_type: Error in expression: " 
00501                  << expr << endl;
00502             cerr << "Intrinsic required to have " << tab.num_req_params(index)
00503                  << " parameters" << endl;
00504             p_abort("Invalid number of parameters");
00505         }
00506     
00507         int num_params = expr.parameters_guarded().arg_list().entries();
00508 
00509         /// ...  Make sure there are the correct number of parameters
00510         /// ...  NOTE: if the number of paramters is listed as 0, the number 
00511         /// ...  is variable.
00512 
00513         if ((num_params < tab.num_req_params(index)) ||
00514             ((tab.num_params(index) != 0) && 
00515              (num_params > tab.num_params(index)))) {
00516 
00517             cerr << "compute_intrinsic_type: Error in expression: " 
00518                  << expr << endl;
00519             cerr << "Intrinsic required to have between "
00520                  << tab.num_req_params(index) << " and "
00521                  << tab.num_params(index)
00522                  << " parameters" << endl;
00523  
00524             p_abort("Invalid number of parameters");
00525         }
00526 
00527         /// ...  Make sure the parameters are of the correct type
00528         /// ...  NOTE: Should also check if they are the correct rank
00529 
00530         int i = 0;
00531 
00532         for (Iterator<Expression> param = expr.parameters_guarded().arg_list();
00533                                   param.valid(); ++param) {
00534             if (!param.current_valid()) {
00535                 cerr << "compute_intrinsic_type: Error in expression: " 
00536                      << expr << endl;
00537                 p_abort("Invalid parameter.");
00538             }
00539 
00540             EXPR_TYPE user_type  = param.current().type().data_type();
00541             EXPR_TYPE table_type = tab.param_type(index, i);
00542 
00543             if (user_type != table_type) {
00544                 /// ...  Types don`t match--check exceptions
00545             
00546                 if ((table_type == INT_OR_REAL_TYPES) &&
00547                     ((user_type == INTEGER_TYPE) ||
00548                      (user_type == REAL_TYPE) ||
00549                      (user_type == DOUBLE_PRECISION_TYPE))) {
00550                     /// ...  OK, nothing to do
00551                 }
00552                 else if ((table_type == REAL_TYPE) &&
00553                          (user_type = DOUBLE_PRECISION_TYPE)) {
00554                     /// ...  OK, nothing to do
00555                 }
00556                 else if ((user_type == REAL_TYPE) &&
00557                          (table_type == DOUBLE_PRECISION_TYPE)) {
00558                     /// ...  OK, nothing to do
00559                 }
00560                 else if (table_type == GENERIC_TYPE) {
00561                     /// ...  OK, nothing to do
00562                 }
00563                 else {  /// ...  Problem!
00564                     cerr << "compute_intrinsic_type: Error in " 
00565                          << "expression: " << expr << endl;
00566                     cerr << "Type of parameter " << i
00567                          << " is invalid." << endl;
00568                     cerr << "Type found = " << user_type << ".  Type "
00569                          << "expected = " << table_type << "." << endl;
00570             
00571                     p_abort("Invalid parameter.");
00572                 }
00573             }
00574         
00575 
00576             int user_rank  = param.current().type().rank();
00577             int table_rank = tab.param_req_rank(index, i);
00578         
00579             if (param.current().type().rank_known() == 1) {  /// ...  make sure rank is known
00580                 if (((table_rank == SCALAR) && (user_rank > 0)) ||
00581                     ((table_rank == ARRAY) && (user_rank == 0))) {
00582                     cerr << "compute_intrinsic_type: Error in " 
00583                          << "expression: " << expr << endl;
00584                     cerr << "Rank of parameter " << i
00585                          << " is invalid." << endl;
00586                     cerr << "Rank found = " << user_rank << ". ";
00587 
00588                     switch (table_rank) {
00589                     case SCALAR:
00590                         cerr << "scalar"; break;
00591                     case ARRAY:
00592                         cerr << "array"; break;
00593                     case SCALAR_OR_ARRAY:
00594                         cerr << "scalar or array"; break;
00595                     case SPECIAL:
00596                         cerr << "special"; break;
00597                     }
00598 
00599                     cerr << " expected." << endl;
00600             
00601                     p_abort("Invalid parameter.");
00602                 }
00603             }
00604         
00605             i = (i < 3) ? i+1 : 3;  /// ...  if there are more than 4 params,
00606                                     /// ...  type-check using the 4th         
00607         }
00608         
00609         /// ...  Determine result type -- set the expr`s type.
00610         /// ...  First, set the type kind
00611     
00612         EXPR_TYPE table_type;
00613     
00614         switch (table_type = tab.return_type(index)) {
00615         case REAL_TYPE: 
00616         case INTEGER_TYPE: 
00617         case COMPLEX_TYPE: 
00618         case LOGICAL_TYPE:
00619         case CHARACTER_TYPE: 
00620         case DOUBLE_PRECISION_TYPE:
00621             {
00622                 (CASTAWAY(Type &) expr.type()).set(table_type, 
00623                                                    tab.return_length(index));
00624             }
00625             break;
00626         
00627         case INT_OR_REAL_TYPES: 
00628         case GENERIC_TYPE:
00629             {
00630                 /// ...  The type is taken from the type of the first parameter
00631                 /// ...  unless the special_type flag is up, in which case it 
00632                 /// ...  is done on a case by case basis.
00633         
00634                 if (!tab.return_special(index)) 
00635                     expr.type(expr.parameters_guarded().arg_list()[0].type());
00636                 else {
00637                     if (intrin == "ABS") {
00638                         /// ...  1st param type
00639 
00640                         const Type & param_type 
00641                             = expr.parameters_guarded().arg_list()[0].type();
00642 
00643                         if ((param_type.data_type() == REAL_TYPE) || 
00644                             (param_type.data_type() == INTEGER_TYPE) ||
00645                             (param_type.data_type() == DOUBLE_PRECISION_TYPE)) {
00646                           expr.type(param_type);
00647                         }
00648                         else if (param_type.data_type() == COMPLEX_TYPE) 
00649                             expr.type( make_type(REAL_TYPE) );
00650                         else {
00651                             report_param_error(expr, "ABS", 1, 
00652                                                "INTEGER/REAL/COMPLEX");
00653                         }
00654                     }
00655                     else if ((intrin == "RESHAPE") ||
00656                              (intrin == "TRANSFER")) {
00657                         /// ...  take type from 2nd argument
00658 
00659                         expr.type( expr.parameters_guarded().arg_list()[
00660                                     1].type() );
00661                     }
00662                     else if ((intrin == "MATMUL") || (intrin == "DOTPRODUCT")) {
00663                         /// ...  use rules from table 7.1.4
00664                 
00665                         Type lt =
00666                             expr.parameters_guarded().arg_list()[0].type();
00667                         Type rt =
00668                             expr.parameters_guarded().arg_list()[1].type();
00669 
00670                         int lrank = lt.rank();
00671                         int rrank = lt.rank();
00672 
00673                         lt.redimension(0);     /// ...  make scalar to avoid
00674                         rt.redimension(0);     /// ...  rank conflicts
00675                 
00676                         if ((intrin == "DOTPRODUCT") &&
00677                             (lt.data_type() == LOGICAL_TYPE) &&
00678                             (rt.data_type() == LOGICAL_TYPE)) {
00679                             /// ...  log * log = log for dotproduct
00680                             expr.type( make_type(LOGICAL_TYPE) );
00681                         }
00682                         else {
00683                             expr.type( expr_type(MULT_OP, lt, rt) );
00684                         }
00685 
00686                         lt.redimension(lrank);
00687                         rt.redimension(rrank);
00688                     }
00689                 }
00690             }
00691             break;      
00692 
00693         default:
00694             {
00695                 cerr << "compute_intrinsic_type: Error in " 
00696                      << "expression: " << expr << endl;
00697                 cerr << "Type found = " << table_type << endl;
00698             
00699                 p_abort( "compute_intrinsic_type: unexpected result type "
00700                          "found in intrinsic table." );
00701             }
00702             break;
00703         }
00704 
00705         /// ...  Set the resulting type shape
00706 
00707         int shape = tab.return_shape(index);
00708 
00709         if (shape == SCALAR) {
00710             (CASTAWAY(Type &) expr.type()).redimension(0);
00711         }
00712         else if ((shape == ARRAY) || (shape == SCALAR_OR_ARRAY)) {
00713             /// ...  Take the shape from the shape of the first argument
00714             /// ...  1st param type
00715 
00716             const Type & param_type 
00717                 = expr.parameters_guarded().arg_list()[0].type();
00718         
00719             if (param_type.rank_known())
00720                 (CASTAWAY(Type &) expr.type()).redimension(param_type.rank());
00721             else
00722                 (CASTAWAY(Type &) expr.type()).rank_known(False);       
00723         }
00724         else {
00725             /// ...  shape == SPECIAL
00726             /// ...  Use rules derived from keywords or match on names
00727 
00728             /// ...  Intrinsic type: INTRINSIC(MASK, DIM)
00729             /// ...  scalar if DIM absent; else it is rank(MASK) - 1
00730             /// ...         * OR *
00731             /// ...  Intrinsic type: INTRINSIC(ARRAY, DIM, MASK)
00732             /// ...  scalar if DIM absent 
00733             /// ...  otherwise rank is rank(ARRAY) - 1
00734             /// ...      * HANDLED THE SAME *
00735         
00736             if (((tab.param_key(index, 0) == "MASK") &&
00737                 (tab.param_key(index, 1) == "DIM"))
00738             || ((tab.param_key(index, 0) == "ARRAY") &&
00739                 (tab.param_key(index, 1) == "DIM") &&
00740                 (tab.param_key(index, 2) == "MASK"))) {
00741         
00742                 if (num_params == 1)
00743                     (CASTAWAY(Type &) expr.type()).redimension(0);
00744                 else {
00745                     /// ...  1st param type
00746 
00747                     const Type & param_type 
00748                         = expr.parameters_guarded().arg_list()[0].type();
00749 
00750                     if (param_type.rank_known()) {
00751                         (CASTAWAY(Type &) expr.type()).redimension(
00752                                                         param_type.rank() - 1);
00753                     }
00754                     else {
00755                         (CASTAWAY(Type &) expr.type()).rank_known(False);
00756                     }
00757                 }
00758             }
00759             else if ((tab.param_key(index, 0) == "ARRAY") &&
00760                      (tab.param_key(index, 1) == "MASK")) {
00761                 /// ...  Intrinsic type: INTRINSIC(ARRAY, MASK)
00762                 /// ...  result is an array of rank 1
00763                 (CASTAWAY(Type &) expr.type()).redimension(1);
00764             }
00765             else if ((tab.param_key(index, 0) == "MATRIX_A") &&
00766                      (tab.param_key(index, 1) == "MATRIX_B")) {
00767                 /// ...  MATMUL-style intrinsic
00768 
00769                 int rank_0 =
00770                     expr.parameters_guarded().arg_list()[0].type().rank();
00771                 int rank_1 =
00772                     expr.parameters_guarded().arg_list()[1].type().rank();
00773         
00774                 if (((rank_0 == 1) && (rank_1 == 2)) ||
00775                     ((rank_0 == 2) && (rank_1 == 1))) {
00776                     (CASTAWAY(Type &) expr.type()).redimension(1);
00777                 }
00778                 else if ((rank_0 == 2) && (rank_1 == 2)) {
00779                     (CASTAWAY(Type &) expr.type()).redimension(2);
00780                 }
00781                 else {
00782                     cerr << "compute_intrinsic_type: Error in " 
00783                          << "expression: " << expr << endl;
00784 
00785                     cerr << "First argument has rank " 
00786                          << rank_0 << endl;
00787                     cerr << "and second argument has rank " 
00788                          << rank_1 << "." << endl;
00789                     cerr << "Illegal combination for matrix multiplication."
00790                          << endl;
00791                 
00792                     p_abort( "compute_intrinsic_type: illegal parameters "
00793                              "found in intrinsic MATMUL." );
00794                 }
00795             }       
00796             else if ((intrin == "LBOUND") || (intrin == "UNBOUND"))  {
00797             /// ...  Intrinsic violates derived rules--handle case by case
00798             /// ...  scalar if dim present, else rank 1
00799 
00800             if (num_params == 2)  /// ...  DIM is present
00801                 (CASTAWAY(Type &) expr.type()).redimension(0);
00802             else
00803                 (CASTAWAY(Type &) expr.type()).redimension(1);
00804             }
00805         }
00806     }
00807     else {   
00808         /// ...  intrinsic _DOES_ require global special handling
00809         /// ...  handle on a case by case basis
00810     }
00811 }
00812 
00813 
00814 /// Assuming the types of all of expr's subexpressions are complete
00815 /// (i.e. contain dimension info), determine expr's complete type.
00816 
00817 void 
00818 determine_root_expr_type(Expression & expr)
00819 {
00820     IntrinsicTable intrin_tab;
00821     
00822     switch (expr.op()) {
00823     case COMPLEX_OP:            
00824         /// ...  Mark as a scalar
00825         (CASTAWAY(Type &) expr.type()).redimension(0);  
00826         break;
00827     
00828     case ARRAY_REF_OP: 
00829         {
00830             /// ...  Rank = # of COLON_OPs in the list of subscripts
00831 
00832             int rank = 0;
00833 
00834             for (Iterator<Expression> expr_iter = expr.subscript().arg_list();
00835                                       expr_iter.valid(); ++expr_iter) {
00836                 if (!expr_iter.current_valid()) {           
00837                     cerr << "Invalid subscript found in array: " 
00838                          << expr << "while determining type.";
00839                     p_abort( "determine_root_expr_type: invalid expression" );
00840                 }
00841                 else if (expr_iter.current().op() == COLON_OP) {
00842                     rank++;
00843                 }
00844             }
00845 
00846             (CASTAWAY(Type &) expr.type()).redimension(rank);
00847         }
00848         break;
00849 
00850     case FUNCTION_CALL_OP: 
00851         {
00852             /// ...  Type is the same as the first sub-expression's type
00853 
00854             if (expr.function().symbol().type().rank_known()) {
00855                 (CASTAWAY(Type &) expr.type()).redimension(
00856                                         expr.function().symbol().type().rank());
00857             }
00858             else {
00859                 (CASTAWAY(Type &) expr.type()).rank_known(False);
00860             }
00861         }
00862         break;
00863 
00864     case INTRINSIC_CALL_OP: 
00865         {
00866             /// ...  Use the intrinsic table.
00867 
00868             compute_intrinsic_type(expr);
00869 
00870             /// ...  (CASTAWAY(Type &) expr.type()).rank_known(False);
00871             /// ...  (CASTAWAY(Type &) expr.type()).set(UNKNOWN_TYPE);
00872         }
00873         break;
00874 
00875     case LAMBDA_CALL_OP:  /// ...  Statement functions must be scalar
00876     case ARG_OP:
00877     case RETURN_OP:  
00878         { 
00879             /// ...  Return integer is scalar
00880     
00881             (CASTAWAY(Type &) expr.type()).redimension(0);
00882         }
00883         break;
00884 
00885     case U_PLUS_OP:   /// ...  unary operations take the type from their
00886     case U_MINUS_OP:  /// ...  sub-expression.
00887     case NOT_OP:
00888     case PAREN_OP: 
00889         {
00890             if (expr.expr_valid())
00891                 expr.type(expr.expr_guarded().type());
00892             else
00893                 (CASTAWAY(Type &) expr.type()).rank_known(False);
00894         }
00895         break;
00896 
00897     case OR_OP: 
00898     case AND_OP: 
00899     case EQV_OP: 
00900     case NEQV_OP:
00901     case ADD_OP: 
00902     case MULT_OP: 
00903     case CONCAT_OP: 
00904         {
00905             Iterator<Expression> xiter = expr.arg_list();
00906     
00907             while (!xiter.current_valid() && xiter.valid()) {
00908                 ++xiter;
00909 
00910                 if (!xiter.valid()) {
00911                     cerr << "NonBinary expression with no arguments: " 
00912                          << expr << endl;
00913                     p_abort("determine_root_expr_type: fatal condition");
00914                 }
00915             }
00916 
00917             Type * type_so_far = xiter.current().type_ref();
00918     
00919             for ( ++xiter; xiter.valid(); ++xiter ) {
00920                 if (xiter.current_valid()) {
00921             Type new_type = expr_type( expr.op(), *type_so_far, 
00922                         xiter.current().type());
00923             delete type_so_far;
00924             type_so_far = new Type(new_type);
00925         }
00926             }
00927 
00928             expr.type( *type_so_far );
00929         /// ...  silvius:
00930         delete type_so_far;
00931         }   
00932         break;
00933 
00934     case EQ_OP: 
00935     case NE_OP: 
00936     case LT_OP: 
00937     case LE_OP: 
00938     case GT_OP:
00939     case GE_OP: 
00940     case SUB_OP: 
00941     case DIV_OP:
00942     case INTDIV_OP:
00943     case RATDIV_OP:
00944     case EXP_OP: 
00945     case SUBSTRING_OP:  
00946     case KEYPAIR_OP:  
00947         {
00948             /// ...  Infer ranks of BinaryExprs. Determine using type-inference 
00949             /// ...  routines.  If a sub-expression does not exist, use the type 
00950             /// ...  of the existing sub-expression.
00951     
00952             if (expr.left_valid()) {
00953                 if (expr.right_valid()) {
00954                     expr.type( expr_type(expr.op(), 
00955                                          expr.left_guarded().type(),
00956                                          expr.right_guarded().type()));
00957                 }
00958                 else {
00959                     expr.type( expr.left_guarded().type() );
00960                 }
00961             }
00962             else {
00963                 if (expr.right_valid()) 
00964                     expr.type( expr.right_guarded().type() );
00965                 else {
00966                     (CASTAWAY(Type &) expr.type()).rank_known(False);
00967                 }
00968             }
00969         }
00970         break;
00971 
00972     case LABEL_OP:  /// ...  Rank makes no sense in these contexts
00973     case IO_STAR_OP:
00974     case FORMAT_OP:
00975     case DO_OP:
00976     case EQUAL_OP:
00977     case COMMA_OP:
00978     case COLON_OP:
00979     case OMEGA_OP:
00980     case REPSTAR_OP:
00981     case TABLE_ENTRY:
00982     case STMT_LABEL_OP:
00983     case INFINITY_OP:
00984 
00985     case ALPHA_OP:
00986     case GAMMA_OP:   
00987     case MU_OP:      
00988     case THETA_OP:
00989     case ETA_OP:
00990 
00991     default: 
00992         {
00993             (CASTAWAY(Type &) expr.type()).rank_known(False);
00994         }
00995         break;
00996     }
00997 }
00998 
00999 /// Determine the appropriate dimensionality of 'expr' based on it's
01000 /// sub-expression's or Symbol's type.  Update the Type with dimension
01001 /// data.  WARNING: This routine makes heavy use of casting away
01002 /// consts in order to modify the const type expression.
01003 
01004 void 
01005 propagate_expr_types(Expression & expr)
01006 {
01007     if (expr.op() == ID_OP) {
01008         /// ...  An IDExpr has the same dimensionality as it`s symbol
01009         expr.type( expr.symbol().type() );
01010     }
01011     else if ((expr.op() == INTEGER_CONSTANT_OP)  ||
01012              (expr.op() == REAL_CONSTANT_OP)  ||
01013              (expr.op() == STRING_CONSTANT_OP)  ||
01014              (expr.op() == LOGICAL_CONSTANT_OP)  ||
01015              (expr.op() == HOLLERITH_CONSTANT_OP)) {
01016         /// ...  mark constants as scalar (NOTE: this does not handle
01017         /// ...  array constants)
01018         
01019         (CASTAWAY(Type &) expr.type()).redimension(0);  
01020     }
01021     else if (expr.arg_list().entries() > 0) {
01022         /// ...  Determine types of the sub-expressions
01023 
01024         for (Iterator<Expression> sub_expr_iter = expr.arg_list();
01025                                   sub_expr_iter.valid(); ++sub_expr_iter) {
01026             if (sub_expr_iter.current_valid())
01027                 propagate_expr_types(sub_expr_iter.current());
01028         }
01029         
01030         determine_root_expr_type(expr);
01031     }
01032 }
01033 
01034 ////////////////////////////////////////////////////////////
01035 ////////////////////////////////////////////////////////////
01036 
01037 static Boolean
01038 is_arithmetic_type(EXPR_TYPE type)
01039 {
01040     return (type == INTEGER_TYPE) || (type == REAL_TYPE) ||
01041            (type == DOUBLE_PRECISION_TYPE) || (type == COMPLEX_TYPE);
01042 }
01043 
01044 static Type
01045 arithmetic_result_type(const Type & type1, const Type & type2, const int rank)
01046 {
01047     EXPR_TYPE       type1_type = type1.data_type();
01048     EXPR_TYPE       type2_type = type2.data_type();
01049     int             type1_size = type1.size();
01050     int             type2_size = type2.size();
01051 
01052     p_assert(is_arithmetic_type(type1_type) && is_arithmetic_type(type2_type),
01053              "Both types must be arithmetic");
01054 
01055     if (type1_type == type2_type)
01056         return make_type(type1_type, max(type1_size, type2_size), rank);
01057 
01058     switch (type1_type) {
01059     case INTEGER_TYPE:
01060         if (type2_type == INTEGER_TYPE)
01061             return make_type(type1_type, max(type1_size, type2_size), rank);
01062         else
01063             return make_type(type2_type, type2_size, rank);
01064 
01065     case REAL_TYPE:
01066         if (type2_type == INTEGER_TYPE)
01067             return make_type(type1_type, type1_size, rank);
01068         else if (type2_type == REAL_TYPE)
01069             return make_type(type1_type, max(type1_size, type2_size), rank);
01070         else
01071             return make_type(type2_type, type2_size, rank);
01072 
01073     case DOUBLE_PRECISION_TYPE:
01074         if ((type2_type == INTEGER_TYPE) || (type2_type == REAL_TYPE))
01075             return make_type(type1_type, type1_size, rank);
01076         else if (type2_type == DOUBLE_PRECISION_TYPE)
01077             return make_type(type1_type, max(type1_size, type2_size), rank);
01078         else
01079             return make_type(type2_type, type2_size, rank);
01080 
01081     case COMPLEX_TYPE:
01082         if ((type2_type == INTEGER_TYPE) || (type2_type == REAL_TYPE) ||
01083             (type2_type == DOUBLE_PRECISION_TYPE))
01084             return make_type(type1_type, type1_size, rank);
01085         else
01086             return make_type(type2_type, max(type1_size, type2_size), rank);
01087     default:
01088         cout << type1_type << endl;
01089         p_abort("Unknown arithmetic type");
01090     }
01091 
01092     /// ...  this return should never happen
01093     return make_type(UNDEFINED_TYPE);
01094 }
01095 
01096 Type 
01097 string_type(const char *data_string, Boolean ignore_errors GIV(False))
01098 {
01099     int             hollerith_len_int;
01100     int             string_len;
01101     int             len = strlen(data_string);
01102     Boolean         havdot = False;
01103     Boolean         havexp = False;
01104     Boolean         havdbl = False;
01105     Boolean         havhol = False;
01106     Boolean         error = False;
01107 
01108     char           *copy_string = upcase_ch(data_string);
01109 
01110     if ((strcmp(copy_string, ".TRUE.") == 0) ||
01111         (strcmp(copy_string, ".FALSE.") == 0)) {
01112         delete[] copy_string;
01113 
01114         return make_type(LOGICAL_TYPE);
01115     }
01116 
01117     if ((copy_string[0] == '\'') &&
01118         (copy_string[len - 1] == '\'')) {
01119 
01120         /// ...  We have a string constant - count up its real length ('' == ')
01121 
01122         string_len = fortran_string_length(copy_string);
01123         delete[] copy_string;
01124 
01125         return make_type(CHARACTER_TYPE, string_len);
01126     }
01127 
01128     if ((copy_string[0] == '\"') &&
01129         (copy_string[len - 1] == '\"')) {
01130 
01131         /// ...  We have a string constant with double quotes -
01132         /// ...  convert to single quotes, then count up its real length ('' == ')
01133 
01134         char *single_quotes = double_to_single_quoted(copy_string);
01135         string_len = fortran_string_length(single_quotes);
01136         delete[] copy_string;
01137         delete[] single_quotes;
01138 
01139         return make_type(CHARACTER_TYPE, string_len);
01140     }
01141 
01142     for (int i = 0; i < len; ++i) {
01143         if (copy_string[i] == '.') {
01144             if (havdot) {
01145                 error = True;
01146                 break;
01147             }
01148             havdot = True;
01149         }
01150         else if ((copy_string[i] == 'D') || (copy_string[i] == 'E')) {
01151             if (havexp) {
01152                 error = True;
01153                 break;
01154             }
01155             havexp = True;
01156 
01157             if (copy_string[i] == 'D')
01158                 havdbl = True;
01159         }
01160         else if (copy_string[i] == 'H') {
01161 
01162             /// ...  If nothing but digits thus far, OK
01163 
01164             if (!havdot && !havexp && !error && !havhol) {
01165                 char           *hollerith_len = new char[i + 1];
01166 
01167                 strncpy(hollerith_len, copy_string, i);
01168                 hollerith_len[i] = '\000';
01169                 sscanf(hollerith_len, "%d", &hollerith_len_int);
01170 
01171                 /// ...  Match stated length with string length
01172 
01173                 if (len - (i + 1) >= hollerith_len_int)
01174                     havhol = True;
01175                 else
01176                     error = True;
01177             }
01178             else
01179                 error = True;
01180         }
01181         else if (((i == 0) || havexp) &&
01182                  ((copy_string[i] == '-') ||
01183                   (copy_string[i] == '+'))) {
01184             /// ...  Fine - all is OK, keep going
01185         }
01186         else if (!isdigit(copy_string[i])) {
01187             error = True;
01188         }
01189     }
01190 
01191     delete[] copy_string;
01192 
01193     if (error) {
01194         if (ignore_errors) 
01195             return make_type(UNDEFINED_TYPE);
01196         cout << data_string << endl;
01197         p_abort("String is not a valid Fortran constant");
01198     }
01199 
01200     if (havhol) 
01201         return make_type(CHARACTER_TYPE, hollerith_len_int);
01202 
01203     if (!havdot && !havexp) 
01204         return make_type(INTEGER_TYPE);
01205 
01206     if (havdbl) 
01207         return make_type(DOUBLE_PRECISION_TYPE);
01208     else 
01209         return make_type(REAL_TYPE);
01210 }
01211 
01212 /// Determine the rank of an intrinsic binary operator using the
01213 /// following rule: "The shape of the result of '[x1] op x2'
01214 /// is the shape of x2 if op is unary or if x1 is scalar, and is
01215 /// the shape of x1 otherwise".  (section 7.1.4.2, FORTRAN 8x spec.)
01216 /// This results in a failed polaris assertion if the types are
01217 /// not in shape conformance.  Returning -1 indicates that the
01218 /// rank is not known.
01219 
01220 int 
01221 compute_rank(const Type & left_type, const Type & right_type, const OP_TYPE op)
01222 {
01223     if (!left_type.rank_known())
01224         return -1;
01225     else if (!right_type.rank_known()) {
01226         if (left_type.is_scalar())
01227             return -1;
01228         else
01229             return left_type.rank();
01230     }
01231     else {
01232         /// ...  both ranks are known
01233 
01234         if (left_type.is_scalar())
01235             return right_type.rank();
01236         else if (right_type.is_scalar())
01237             return left_type.rank();
01238         else {
01239             /// ...  They are both arrays
01240 
01241             if (right_type.rank() != left_type.rank()) {
01242                 /// ...  Types not in shape conformance
01243                 cerr << "Types in intrinsic operation found"
01244                      << " not to be in shape conformance" << endl;
01245         cerr << "for op number " << (int) op << endl;
01246                 cerr << "Left: " << left_type << endl;
01247                 cerr << "Right: " << right_type << endl;
01248 
01249                 p_abort("compute_rank::Violation of FORTRAN standard found");
01250             }
01251             return right_type.rank();
01252         }
01253     }
01254 }
01255 
01256 Type 
01257 expr_type(const OP_TYPE op, const Type & left_type, const Type & right_type)
01258 {
01259     EXPR_TYPE       left_type_type, right_type_type;
01260     int             left_type_size, right_type_size;
01261     int             op_rank;
01262     
01263     static int promote_logicals = -1;
01264     static int promote_integers = -1;
01265 
01266     if (promote_logicals < 0)
01267         promote_logicals = switch_value("prom_logical");
01268 
01269     if (promote_integers < 0)
01270     promote_integers = switch_value("prom_integer");
01271     
01272     left_type_type = left_type.data_type();
01273     left_type_size = left_type.size();
01274 
01275     right_type_type = right_type.data_type();
01276     right_type_size = right_type.size();
01277 
01278     op_rank = compute_rank(left_type, right_type, op);
01279     
01280     if (left_type_type == UNKNOWN_TYPE || right_type_type == UNKNOWN_TYPE) 
01281         return make_ranked_type(UNKNOWN_TYPE, op_rank);
01282 
01283     switch (op) {
01284     case OR_OP:                 /// ...  NonBinaryExpr operator
01285     case AND_OP:                /// ...  NonBinaryExpr operator
01286     case EQV_OP:                /// ...  NonBinaryExpr operator
01287     case NEQV_OP:               /// ...  NonBinaryExpr operator
01288 
01289         if ((left_type_type == LOGICAL_TYPE) && 
01290             (right_type_type == LOGICAL_TYPE)) 
01291             return make_ranked_type(LOGICAL_TYPE, op_rank);
01292 
01293     if (promote_integers > 0) {
01294         if (((left_type_type == INTEGER_TYPE) &&
01295          (right_type_type == INTEGER_TYPE)) ||
01296         ((left_type_type == INTEGER_TYPE) &&
01297          (right_type_type == LOGICAL_TYPE)) ||
01298         ((left_type_type == LOGICAL_TYPE) &&
01299          (right_type_type == INTEGER_TYPE)))
01300 
01301         return make_ranked_type(LOGICAL_TYPE, op_rank);
01302     }
01303 
01304         cout << left_type << ' ' << op_string[op] << ' ' << right_type << endl;
01305         p_abort("Bad type combination");
01306 
01307         return make_type(UNDEFINED_TYPE);
01308 
01309     case KEYPAIR_OP:              /// ...  BinaryExpr operator
01310         return right_type;
01311 
01312     case EQ_OP:
01313     case NE_OP:
01314     case LT_OP:
01315     case LE_OP:
01316     case GT_OP:
01317     case GE_OP:
01318 
01319         if (  (is_arithmetic_type(left_type_type) 
01320             && is_arithmetic_type(right_type_type)) ||
01321                ((left_type_type == LOGICAL_TYPE) 
01322             && (right_type_type == LOGICAL_TYPE))   || 
01323               (left_type_type == CHARACTER_TYPE)
01324             && (right_type_type == CHARACTER_TYPE)) 
01325             return make_ranked_type(LOGICAL_TYPE, op_rank);
01326 
01327         cout << left_type << ' ' << op_string[op] << ' ' << right_type << endl;
01328         p_abort("Bad type combination");
01329 
01330         return make_type(UNDEFINED_TYPE);
01331 
01332     case ADD_OP:                /// ...  NonBinaryExpr operator
01333     case MULT_OP:               /// ...  NonBinaryExpr operator
01334     case SUB_OP:
01335     case DIV_OP:
01336     case INTDIV_OP:
01337     case RATDIV_OP:
01338     case EXP_OP:
01339 
01340 #if 0
01341     /// ...  This is only valid for F77, it is possible in F90.
01342         if (((left_type_type == COMPLEX_TYPE) &&
01343              (right_type_type == DOUBLE_PRECISION_TYPE)) ||
01344             ((left_type_type == DOUBLE_PRECISION_TYPE) &&
01345              (right_type_type == COMPLEX_TYPE)))
01346             p_abort("DOUBLE PRECISION prohibited with COMPLEX");
01347 #endif
01348     
01349         if (is_arithmetic_type(left_type_type) &&
01350             is_arithmetic_type(right_type_type)) 
01351             return arithmetic_result_type(left_type, right_type, op_rank);
01352 
01353         if (promote_logicals > 0) {
01354             
01355             if (left_type_type == LOGICAL_TYPE) {
01356                 if (right_type_type == LOGICAL_TYPE) {
01357                     return make_ranked_type(INTEGER_TYPE, op_rank);
01358                 }
01359                 else {
01360                     Type t1 = make_ranked_type(INTEGER_TYPE, left_type.rank());
01361                     return arithmetic_result_type(t1, right_type, op_rank);
01362                 }
01363             } else {
01364                 if (right_type_type == LOGICAL_TYPE) {
01365                     Type t2 = make_ranked_type(INTEGER_TYPE, right_type.rank());
01366                     return arithmetic_result_type(left_type, t2, op_rank);
01367                 }
01368                 cout << left_type << ' ' << op << ' ' << right_type << endl;
01369                 p_abort("Invalid type combination");
01370             }
01371         }
01372         else {
01373             cout << left_type << ' ' << op_string[op] 
01374                  << ' ' << right_type << endl;
01375             p_abort("Bad type combination");
01376             
01377             return make_type(UNDEFINED_TYPE);
01378         }
01379 
01380     case CONCAT_OP:
01381         if ((left_type_type == CHARACTER_TYPE) &&
01382             (right_type_type == CHARACTER_TYPE)) 
01383             return make_type(CHARACTER_TYPE, left_type_size + right_type_size,
01384                              op_rank);
01385 
01386         cout << left_type << ' ' << op_string[op] << ' ' << right_type << endl;
01387         p_abort("Bad type combination");
01388 
01389         return make_type(UNDEFINED_TYPE);
01390 
01391     case COLON_OP:
01392         if (((left_type_type == INTEGER_TYPE)
01393              || (left_type_type == UNDEFINED_TYPE)) &&
01394             ((right_type_type == INTEGER_TYPE)
01395              || (right_type_type == UNDEFINED_TYPE))) 
01396             return make_ranked_type(INTEGER_TYPE, op_rank);
01397 
01398         cout << left_type << ' ' << op_string[op] << ' ' << right_type << endl;
01399         p_abort("Bad type combination");
01400 
01401         return make_type(UNDEFINED_TYPE);
01402 
01403     case COMPLEX_OP:
01404         return make_type(COMPLEX_TYPE, max(left_type_size, right_type_size),
01405                          op_rank);
01406 
01407     case SUBSTRING_OP:
01408         return make_type(CHARACTER_TYPE, 0, op_rank);
01409 
01410     case ARRAY_REF_OP:
01411         return make_type(left_type_type, left_type_size, op_rank);
01412 
01413     case ALPHA_OP:   /// ...  Treat these as normal operations
01414     case GAMMA_OP:   /// ...  but ignore OMEGA_OP arguments
01415     case MU_OP:      
01416     case THETA_OP:
01417     case ETA_OP:
01418 
01419         if (left_type_type == right_type_type
01420             && left_type_size == right_type_size)
01421             return Type( left_type );
01422     else if (right_type_type == VOID_TYPE)
01423         return Type( left_type );
01424     else if (left_type_type == VOID_TYPE)
01425         return Type( right_type);
01426         else if (is_arithmetic_type(left_type_type) &&
01427             is_arithmetic_type(right_type_type)) 
01428             return arithmetic_result_type(left_type, right_type, op_rank);
01429         else if ((left_type_type == CHARACTER_TYPE) &&
01430                  (right_type_type == CHARACTER_TYPE)) 
01431             return make_type(CHARACTER_TYPE,max(left_type_size,right_type_size),
01432                              op_rank);
01433         else {
01434             cout << left_type << ' ' << op_string[op] 
01435                  << ' ' << right_type << endl;
01436             p_abort("Bad type combination");
01437 
01438             return make_type(UNDEFINED_TYPE);
01439         }
01440 
01441     default:
01442         cout << left_type << ' ' << op_string[op] << ' ' << right_type << endl;
01443         p_abort("Bad operator");
01444         break;
01445     }
01446 
01447     return make_type(UNDEFINED_TYPE);
01448 }
01449 
01450 Type 
01451 expr_type(const OP_TYPE op, const List<Expression>&args)
01452 {
01453     int             entries = args.entries();
01454 
01455     p_assert( entries > 0,
01456              "expr_type(const OP_TYPE, const List<Expression> &): "
01457              "args list must be non-empty");
01458 
01459     Iterator<Expression> iter = args;
01460     Type                 type_so_far = iter.current().type();
01461 
01462     for (++iter; iter.valid(); ++iter) 
01463         type_so_far = expr_type(op, type_so_far, iter.current().type());
01464 
01465     return type_so_far;
01466 }
01467 
01468 List<Expression> *
01469 expr_list(Expression * expr1  GIV(0),
01470           Expression * expr2  GIV(0),
01471           Expression * expr3  GIV(0),
01472           Expression * expr4  GIV(0),
01473           Expression * expr5  GIV(0),
01474           Expression * expr6  GIV(0),
01475           Expression * expr7  GIV(0),
01476           Expression * expr8  GIV(0),
01477           Expression * expr9  GIV(0),
01478           Expression * expr10 GIV(0))
01479 {
01480     List<Expression> * list = new List<Expression>;
01481 
01482 # define LIST_EXPR_ADD(expr) if (expr) list->ins_last(expr)
01483 
01484     LIST_EXPR_ADD(expr1);
01485     LIST_EXPR_ADD(expr2);
01486     LIST_EXPR_ADD(expr3);
01487     LIST_EXPR_ADD(expr4);
01488     LIST_EXPR_ADD(expr5);
01489     LIST_EXPR_ADD(expr6);
01490     LIST_EXPR_ADD(expr7);
01491     LIST_EXPR_ADD(expr8);
01492     LIST_EXPR_ADD(expr9);
01493     LIST_EXPR_ADD(expr10);
01494 
01495 # undef LIST_EXPR_ADD
01496 
01497     return list;
01498 }
01499 
01500 Expression     *
01501 constant(int value)
01502 {
01503     return new IntConstExpr((int) value);
01504 }
01505 
01506 Expression     *
01507 constant(const char *data_string)
01508 {
01509     Type            t = string_type(data_string);
01510     EXPR_TYPE       e = t.data_type();
01511 
01512     switch (e) {
01513     case LOGICAL_TYPE:
01514         return new LogicalConstExpr(data_string);
01515 
01516     case CHARACTER_TYPE:
01517         if (data_string[0] == '\'')
01518             return new StringConstExpr(data_string);
01519         else if (data_string[0] == '"') {
01520             /// ...  Convert to single-quoted character constant
01521             char *single = double_to_single_quoted(data_string);
01522             Expression *string_expr = new StringConstExpr(single);
01523             delete [] single;
01524             return string_expr;
01525         }
01526         else
01527             return new HollerithConstExpr(data_string);
01528 
01529     case REAL_TYPE:
01530         return new RealConstExpr(REAL_TYPE, data_string);
01531 
01532     case DOUBLE_PRECISION_TYPE:
01533         return new RealConstExpr(DOUBLE_PRECISION_TYPE, data_string);
01534 
01535     case INTEGER_TYPE:
01536         {
01537             int             value;
01538 
01539             sscanf((char *) data_string, "%d", &value);
01540             return new IntConstExpr(value);
01541         }
01542 
01543     default:
01544         cout << e << endl;
01545         p_abort("Unexpected type for a constant");
01546         break;
01547     }
01548 
01549     return 0;
01550 }
01551 
01552 Expression     *
01553 keyword(const char *data_string)
01554 {
01555     p_assert( data_string, "keyword is null" );
01556 
01557     return new KeyExpr( data_string );
01558 }
01559 
01560 Expression     *
01561 complex(Expression * real, Expression * imag)
01562 {
01563     return new ComplexExpr(real, imag);
01564 }
01565 
01566 Expression     *
01567 array_reference(Expression * array, Expression * subscripts)
01568 {
01569     p_assert((array != NULL) && (subscripts != NULL),
01570              "arg(s) to *arrayref* must be non-NULL");
01571 
01572     Expression *expr = new ArrayRefExpr(array->type(), array, subscripts);
01573 
01574     determine_root_expr_type(*expr);
01575 
01576     return expr;
01577 }
01578 
01579 static inline Expression     *
01580 create_nonbinary(List<Expression>*args, OP_TYPE op_type, const char *func_name)
01581 {
01582     if (args->entries() <= 0) {
01583         char            buf[1000];
01584 
01585         sprintf(buf, "%s(List<Expression> *): args list must be non-empty",
01586                 func_name);
01587 
01588         p_abort(buf);
01589     }
01590 
01591     return new NonBinaryExpr(op_type, expr_type(op_type, *args), args);
01592 }
01593 
01594 Expression     *
01595 add(Expression * expr1, Expression * expr2)
01596 {
01597     p_assert((expr1 != NULL) && (expr2 != NULL),
01598              "arg(s) to *add* must be non-NULL");
01599 
01600     return new NonBinaryExpr(ADD_OP,
01601                              expr_type(ADD_OP, expr1->type(), expr2->type()),
01602                              expr1, expr2);
01603 }
01604 
01605 Expression     *
01606 add(List<Expression> *args)
01607 {
01608     return create_nonbinary(args, ADD_OP, "add");
01609 }
01610 
01611 Expression     *
01612 sub(Expression *expr1, Expression *expr2)
01613 {
01614     p_assert((expr1 != NULL) && (expr2 != NULL),
01615              "arg(s) to *sub* must be non-NULL");
01616 
01617     return new BinaryExpr(SUB_OP,
01618                           expr_type(SUB_OP, expr1->type(), expr2->type()),
01619                           expr1, expr2);
01620 }
01621 
01622 Expression     *
01623 mul(Expression * expr1, Expression * expr2)
01624 {
01625     p_assert((expr1 != NULL) && (expr2 != NULL),
01626              "arg(s) to *mul* must be non-NULL");
01627 
01628     return new NonBinaryExpr(MULT_OP,
01629                              expr_type(MULT_OP, expr1->type(), expr2->type()),
01630                              expr1, expr2);
01631 }
01632 
01633 Expression     *
01634 mul(List<Expression>*args)
01635 {
01636     return create_nonbinary(args, MULT_OP, "mul");
01637 }
01638 
01639 Expression     *
01640 div(Expression * expr1, Expression * expr2)
01641 {
01642     p_assert((expr1 != NULL) && (expr2 != NULL),
01643              "arg(s) to *div* must be non-NULL");
01644 
01645     return new BinaryExpr(DIV_OP,
01646                           expr_type(DIV_OP, expr1->type(), expr2->type()),
01647                           expr1, expr2);
01648 }
01649 
01650 Expression     *
01651 exponent(Expression * expr1, Expression * expr2)
01652 {
01653     p_assert((expr1 != NULL) && (expr2 != NULL),
01654              "arg(s) to *exp* must be non-NULL");
01655 
01656     return new BinaryExpr(EXP_OP,
01657                           expr_type(EXP_OP, expr1->type(), expr2->type()),
01658                           expr1, expr2);
01659 }
01660 
01661 Expression     *
01662 keypair(Expression * expr1, Expression * expr2)
01663 {
01664     p_assert((expr1 != NULL) && (expr2 != NULL),
01665              "arg(s) to *keypair* must be non-NULL");
01666 
01667     return new BinaryExpr(KEYPAIR_OP, make_type(VOID_TYPE), expr1, expr2);
01668 }
01669 
01670 Expression *
01671 eq(Expression * expr1, Expression * expr2)
01672 {
01673     p_assert((expr1 != NULL) && (expr2 != NULL),
01674              "arg(s) to *eq* must be non-NULL");
01675 
01676     return new BinaryExpr(EQ_OP,
01677                           expr_type(EQ_OP, expr1->type(), expr2->type()),
01678                           expr1, expr2);
01679 }
01680 
01681 Expression *
01682 ne(Expression * expr1, Expression * expr2)
01683 {
01684     p_assert((expr1 != NULL) && (expr2 != NULL),
01685              "arg(s) to *ne* must be non-NULL");
01686 
01687     return new BinaryExpr(NE_OP,
01688                           expr_type(NE_OP, expr1->type(), expr2->type()),
01689                           expr1, expr2);
01690 }
01691 
01692 Expression *
01693 lt(Expression * expr1, Expression * expr2)
01694 {
01695     p_assert((expr1 != NULL) && (expr2 != NULL),
01696              "arg(s) to *lt* must be non-NULL");
01697 
01698     return new BinaryExpr(LT_OP,
01699                           expr_type(LT_OP, expr1->type(), expr2->type()),
01700                           expr1, expr2);
01701 }
01702 
01703 Expression *
01704 le(Expression * expr1, Expression * expr2)
01705 {
01706     p_assert((expr1 != NULL) && (expr2 != NULL),
01707              "arg(s) to *le* must be non-NULL");
01708 
01709     return new BinaryExpr(LE_OP,
01710                           expr_type(LE_OP, expr1->type(), expr2->type()),
01711                           expr1, expr2);
01712 }
01713 
01714 Expression *
01715 gt(Expression * expr1, Expression * expr2)
01716 {
01717     p_assert((expr1 != NULL) && (expr2 != NULL),
01718              "arg(s) to *gt* must be non-NULL");
01719 
01720     return new BinaryExpr(GT_OP,
01721                           expr_type(GT_OP, expr1->type(), expr2->type()),
01722                           expr1, expr2);
01723 }
01724 
01725 Expression *
01726 ge(Expression * expr1, Expression * expr2)
01727 {
01728     p_assert((expr1 != NULL) && (expr2 != NULL),
01729              "arg(s) to *ge* must be non-NULL");
01730 
01731     return new BinaryExpr(GE_OP,
01732                           expr_type(GE_OP, expr1->type(), expr2->type()),
01733                           expr1, expr2);
01734 }
01735 
01736 Expression *
01737 or(Expression * expr1, Expression * expr2)
01738 {
01739     p_assert((expr1 != NULL) && (expr2 != NULL),
01740              "args to *or* must be non-NULL");
01741 
01742     return new NonBinaryExpr(OR_OP,
01743                              expr_type(OR_OP, expr1->type(), expr2->type()),
01744                              expr1, expr2);
01745 }
01746 
01747 Expression *
01748 or(List<Expression> *args)
01749 {
01750     return create_nonbinary(args, OR_OP, "or");
01751 }
01752 
01753 Expression *
01754 and(Expression * expr1, Expression * expr2)
01755 {
01756     p_assert((expr1 != NULL) && (expr2 != NULL),
01757              "arg(s) to *and* must be non-NULL");
01758 
01759     return new NonBinaryExpr(AND_OP,
01760                              expr_type(AND_OP, expr1->type(), expr2->type()),
01761                              expr1, expr2);
01762 }
01763 
01764 Expression *
01765 and(List<Expression> *args)
01766 {
01767     return create_nonbinary(args, AND_OP, "and");
01768 }
01769 
01770 Expression     *
01771 eqv(Expression * expr1, Expression * expr2)
01772 {
01773     p_assert((expr1 != NULL) && (expr2 != NULL),
01774              "arg(s) to *eqv* must be non-NULL");
01775 
01776     return new NonBinaryExpr(EQV_OP,
01777                              expr_type(EQV_OP, expr1->type(), expr2->type()),
01778                              expr1, expr2);
01779 }
01780 
01781 Expression     *
01782 eqv(List<Expression> *args)
01783 {
01784     return create_nonbinary(args, EQV_OP, "eqv");
01785 }
01786 
01787 Expression     *
01788 neqv(Expression * expr1, Expression * expr2)
01789 {
01790     p_assert((expr1 != NULL) && (expr2 != NULL),
01791              "arg(s) to *neqv* must be non-NULL");
01792 
01793     return new NonBinaryExpr(NEQV_OP,
01794                              expr_type(NEQV_OP, expr1->type(), expr2->type()),
01795                              expr1, expr2);
01796 }
01797 
01798 Expression *
01799 neqv(List<Expression>*args)
01800 {
01801     return create_nonbinary(args, NEQV_OP, "neqv");
01802 }
01803 
01804 Expression *
01805 function_call(Expression * expr1, Expression * expr2)
01806 {
01807     p_assert((expr1 != NULL) && (expr2 != NULL), 
01808              "both args to *function_call* must be non-NULL");
01809 
01810     p_assert(expr1->symbol().intrinsic() == NOT_INTRINSIC,
01811              "the symbol argument to function_call() must not be INTRINSIC" );
01812  
01813     return new FunctionCallExpr(expr1->symbol().type(), expr1, expr2);
01814 }
01815 
01816 Expression *
01817 intrinsic_call(Expression * expr1, Expression * expr2)
01818 {
01819     p_assert((expr1 != NULL) && (expr2 != NULL), 
01820              "both args to *intrinsic_call* must be non-NULL");
01821 
01822      p_assert( expr1->symbol().intrinsic() == IS_INTRINSIC,
01823               "the symbol argument to intrinsic_call() must be INTRINSIC" );
01824  
01825     Expression *expr 
01826         = new IntrinsicCallExpr(expr1->symbol().type(), expr1, expr2);
01827 
01828     determine_root_expr_type(*expr);
01829 
01830     return expr;
01831 }
01832 
01833 Expression *
01834 substring(Expression * expr1, Expression * expr2)
01835 {
01836     p_assert((expr1 != NULL) && (expr2 != NULL), 
01837              "both args to *substring* must be non-NULL");
01838 
01839     return new SubStringExpr(expr_type(SUBSTRING_OP,
01840                        expr1->type(),
01841                        expr2->type()),
01842                  expr1,
01843                  expr2);
01844 }
01845 
01846 Expression *
01847 concat(Expression * expr1, Expression * expr2)
01848 {
01849     p_assert((expr1 != NULL) && (expr2 != NULL), 
01850              "both args to *concat* must be non-NULL");
01851 
01852     return new NonBinaryExpr(CONCAT_OP,
01853               expr_type(CONCAT_OP,
01854                     expr1->type(),
01855                     expr2->type()),
01856               expr1,
01857               expr2);
01858 }
01859 
01860 Expression     *
01861 colon(Expression * expr1, Expression * expr2, Expression * expr3 GIV(0))
01862 {
01863     p_assert((expr1 != NULL) || (expr2 != NULL), 
01864              "first two args to *colon* must be non-NULL");
01865 
01866     return new NonBinaryExpr(COLON_OP, make_type(VOID_TYPE),
01867                              expr1, expr2, expr3);
01868 }
01869 
01870 Expression     *
01871 colon(List<Expression> *args)
01872 {
01873     return create_nonbinary(args, COLON_OP, "colon");
01874 }
01875 
01876 Expression * 
01877 comma (List<Expression> *args)
01878 {
01879         return new CommaExpr(args);
01880 }
01881 
01882 Expression *
01883 comma(Expression *expr1, Expression *expr2,
01884       Expression *expr3 GIV(0), Expression *expr4 GIV(0), 
01885       Expression *expr5 GIV(0))
01886 {
01887     p_assert((expr1 != NULL), "arg 1 to *comma* must be non-NULL");
01888     p_assert((expr2 != NULL), "arg 2 to *comma* must be non-NULL");
01889 
01890     return new CommaExpr(expr1, expr2, expr3, expr4, expr5);
01891 }
01892 
01893 Expression     *
01894 comma(Expression * expr1)
01895 {
01896     p_assert((expr1 != NULL), "arg 1 to *comma* must be non-NULL");
01897 
01898     return new CommaExpr(expr1);
01899 }
01900 
01901 Expression *
01902 comma() {
01903     return new CommaExpr();
01904 }
01905     
01906 Expression     *
01907 unary_plus(Expression * expr)
01908 {
01909     p_assert(expr != NULL, "arg to *uplus* must be non-NULL");
01910 
01911     return new UnaryExpr(U_PLUS_OP, expr->type(), expr);
01912 }
01913 
01914 Expression     *
01915 unary_minus(Expression * expr)
01916 {
01917     p_assert(expr != NULL, "arg to *uminus* must be non-NULL");
01918 
01919     return new UnaryExpr(U_MINUS_OP, expr->type(), expr);
01920 }
01921 
01922 Expression     *
01923 do_expression(Expression * expr1,
01924           Expression * expr2)
01925 {
01926     p_assert((expr1 != NULL) || (expr2 != NULL), 
01927              "first two args to *do_expression* must be non-NULL");
01928 
01929     return new DoExpr(expr1, expr2);
01930 }
01931 
01932 Expression     *
01933 equal(Expression * index,
01934       Expression * iter_space)
01935 {
01936     p_assert((index != NULL) || (iter_space != NULL), 
01937              "first two args to *equal* must be non-NULL");
01938 
01939     return new EqualExpr(index->type(), index, iter_space);
01940 }
01941 
01942 Expression     *
01943 not(Expression * expr)
01944 {
01945     p_assert(expr != NULL, "arg to *not* must be non-NULL");
01946 
01947     return new UnaryExpr(NOT_OP, expr->type(), expr);
01948 }
01949 
01950 
01951 Expression     *
01952 paren(Expression * expr)
01953 {
01954     p_assert(expr != NULL, "arg to *par* must be non-NULL");
01955 
01956     return new UnaryExpr(PAREN_OP, expr->type(), expr);
01957 }
01958 
01959 Expression     *
01960 id(const char *varname, const ProgramUnit & pgm)
01961 {
01962     const Symbol         *s = pgm.symtab().find_ref(varname);
01963 
01964     p_assert(s, "Symbol name passed to *id* does not exist in ProgramUnit");
01965     return new IDExpr(s->type(), *s);
01966 }
01967 
01968 Expression     *
01969 id(const Symbol & symbol)
01970 {
01971     return new IDExpr(symbol.type(), symbol);
01972 }
01973 
01974 Expression     *
01975 new_variable(const char *varname,
01976              const Type & t,
01977              ProgramUnit & pgm)
01978 {
01979     Symbol *s = new VariableSymbol(varname, t, NOT_FORMAL, NOT_SAVED);
01980 
01981     pgm.symtab().ins(s);
01982 
01983     return new IDExpr(s->type(), *s);
01984 }
01985 
01986 Expression     *
01987 new_function(const char *funname,
01988              const Type & t,
01989              ProgramUnit & pgm)
01990 {
01991     Symbol *s = new FunctionSymbol(funname, t, IS_EXTERNAL, 
01992                          NOT_INTRINSIC, NOT_FORMAL);
01993     pgm.symtab().ins(s);
01994 
01995     return new IDExpr(s->type(), *s);
01996 }
01997 
01998 Expression     *
01999 new_intrinsic(const char *funname,
02000               const Type & t,
02001               ProgramUnit & pgm)
02002 {
02003     Symbol         *s = new FunctionSymbol(funname, t, NOT_EXTERNAL,
02004                          IS_INTRINSIC, NOT_FORMAL);
02005     pgm.symtab().ins(s);
02006 
02007     return new IDExpr(s->type(), *s);
02008 }
02009 
02010 Expression     *
02011 new_subroutine(const char *funname,
02012                ProgramUnit & pgm)
02013 {
02014     Symbol         *s = new SubroutineSymbol(funname, IS_EXTERNAL,
02015                            NOT_INTRINSIC, NOT_FORMAL);
02016     pgm.symtab().ins(s);
02017 
02018     return new IDExpr(s->type(), *s);
02019 }
02020 
02021 Expression     *
02022 new_array_variable(const char *varname, const Type & t,
02023                    ProgramUnit & pgm, Expression * bounds1,
02024                    Expression * bounds2 GIV(0),
02025                    Expression * bounds3 GIV(0),
02026                    Expression * bounds4 GIV(0),
02027                    Expression * bounds5 GIV(0))
02028 {
02029     ArrayBounds    *ab2 = 0;
02030     ArrayBounds    *ab3 = 0;
02031     ArrayBounds    *ab4 = 0;
02032     ArrayBounds    *ab5 = 0;
02033 
02034     p_assert(bounds1->op() == COLON_OP, 
02035              "Array bound 1 is not a COLON expression");
02036 
02037     ArrayBounds    *ab1 = new ArrayBounds(bounds1->left_guarded().clone(),
02038                                           bounds1->right_guarded().clone());
02039     if (bounds2) {
02040         p_assert(bounds2->op() == COLON_OP, 
02041                  "Array bound 2 is not a COLON expression");
02042 
02043         ab2 = new ArrayBounds(bounds2->left_guarded().clone(),
02044                               bounds2->right_guarded().clone());
02045     }
02046 
02047     if (bounds3) {
02048         p_assert(bounds3->op() == COLON_OP, 
02049                  "Array bound 3 is not a COLON expression");
02050 
02051         ab3 = new ArrayBounds(bounds3->left_guarded().clone(),
02052                               bounds3->right_guarded().clone());
02053     }
02054 
02055     if (bounds4) {
02056         p_assert(bounds4->op() == COLON_OP,
02057                  "Array bound 4 is not a COLON expression");
02058 
02059         ab4 = new ArrayBounds(bounds4->left_guarded().clone(),
02060                               bounds4->right_guarded().clone());
02061     }
02062 
02063     if (bounds5) {
02064         p_assert(bounds5->op() == COLON_OP,
02065                  "Array bound 5 is not a COLON expression");
02066 
02067         ab5 = new ArrayBounds(bounds5->left_guarded().clone(),
02068                               bounds5->right_guarded().clone());
02069     }
02070 
02071     Symbol         *s = new VariableSymbol(varname, t, NOT_FORMAL, NOT_SAVED,
02072                          ab1, ab2, ab3, ab4, ab5);
02073 
02074     pgm.symtab().ins(s);
02075 
02076     return new IDExpr(s->type(), *s);
02077 }
02078 
02079 Expression     *
02080 omega()
02081 {
02082     return new OmegaExpr;
02083 }
02084 
02085 Expression     *
02086 null_to_omega(Expression * expr)
02087 {
02088     return (expr) ? expr : omega();
02089 }
02090 
02091 Expression     *
02092 infinity(int s GIV(1))
02093 {
02094     return new InfinityExpr(s);
02095 }
02096 
02097 //------------------------------------------------------------------------ 
02098 
02099 Expression     *
02100 alpha(Expression *parameters)
02101 {
02102     p_assert(parameters,
02103              "parameters argument to *alpha* must be non-NULL");
02104 
02105     return new GSAExpr(ALPHA_OP, expr_type(ALPHA_OP, parameters->arg_list()),
02106                        parameters);
02107 }
02108 
02109 Expression     *
02110 gamma(Expression *gate, Expression *parameters)
02111 {
02112     p_assert(parameters,
02113              "parameters (second) argument to *gamma* must be non-NULL");
02114 
02115     return new GSAExpr(GAMMA_OP, expr_type(GAMMA_OP, parameters->arg_list()),
02116                        parameters, gate);
02117 }
02118 
02119 Expression     *
02120 mu(Expression *parameters)
02121 {
02122     p_assert(parameters,
02123              "parameter argument to *mu* must be non-NULL");
02124 
02125     return new GSAExpr(MU_OP, expr_type(MU_OP, parameters->arg_list()),
02126                        parameters);
02127 }
02128 
02129 Expression     *
02130 theta(Expression *parameters)
02131 {
02132     p_assert(parameters,
02133              "parameter argument to *mu* must be non-NULL");
02134 
02135     return new GSAExpr(THETA_OP, expr_type(THETA_OP, parameters->arg_list()),
02136                        parameters);
02137 }
02138 
02139 Expression      *
02140 eta(Expression *gate, Expression *parameters)
02141 {
02142     p_assert(parameters,
02143              "parameters (second) argument to *eta* must be non-NULL");
02144 
02145     return new GSAExpr(ETA_OP, expr_type(ETA_OP, parameters->arg_list()),
02146                        parameters, gate);
02147 }
02148 
02149 Expression     *
02150 mu(Expression *parameters, Expression * gate)
02151 {
02152     p_assert(parameters,
02153              "parameter argument to *mu* must be non-NULL");
02154 
02155     return new GSAExpr(MU_OP, expr_type(MU_OP, parameters->arg_list()),
02156                        parameters, gate);
02157 }
02158 
02159 //------------------------------------------------------------------------ 
02160 
02161 static void 
02162 _cannot_coerce(const Type & from, EXPR_TYPE to)
02163 {
02164     String          from_str, to_str;
02165 
02166     Type            to_type(to);
02167 
02168     from.format(from_str);
02169     to_type.format(to_str);
02170 
02171     cerr << "\n\nError: coerce(): Tried to coerce from type "
02172          << from_str << " to type " << to_str << endl << endl;
02173 
02174     p_abort("(See above error message)");
02175 }
02176 
02177 static void 
02178 _assert_can_coerce(const Type & from, EXPR_TYPE to,
02179                    EXPR_TYPE from1,
02180                    EXPR_TYPE from2 = (EXPR_TYPE) (-1),
02181                    EXPR_TYPE from3 = (EXPR_TYPE) (-1),
02182                    EXPR_TYPE from4 = (EXPR_TYPE) (-1),
02183                    EXPR_TYPE from5 = (EXPR_TYPE) (-1))
02184 {
02185     EXPR_TYPE       f = from.data_type();
02186 
02187     if (f == from1 || f == from2 || f == from3 || f == from4 || f == from5)
02188         return;
02189 
02190     _cannot_coerce(from, to);
02191 }
02192 
02193 static Expression *
02194 _coerce(Expression * expr, const char *intrin_name,
02195         EXPR_TYPE NOTUSED(type), ProgramUnit & pgm)
02196 {
02197     p_assert(intrin_name, "_coerce(): intrin_name is NULL");
02198 
02199     Type            result_type;/// ...  Select size by default
02200     Symbol         *intrin_sym = pgm.symtab().find_ref(intrin_name);
02201 
02202     if (intrin_sym) {
02203         p_assert(intrin_sym->intrinsic(),
02204                  "_coerce(): Intrinsic name already exists in symbol "
02205                  "table, but is not an intrinsic function");
02206     }
02207     else {
02208         intrin_sym = &pgm.symtab().ins(
02209                              new FunctionSymbol(intrin_name, result_type,
02210                                        NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL));
02211     }
02212 
02213     return new IntrinsicCallExpr(intrin_sym->type(),
02214                                  new IDExpr(intrin_sym->type(),
02215                                             *intrin_sym),
02216                                  new CommaExpr(expr));
02217 }
02218 
02219 Expression     *
02220 coerce(Expression * expr, EXPR_TYPE type, ProgramUnit & pgm)
02221 {
02222     if (type == expr->type().data_type())
02223         return expr;
02224     else {
02225     /// ...         const char     *intrin_name = 0;
02226 
02227         switch (type) {
02228 
02229         case VOID_TYPE:
02230             _cannot_coerce(expr->type(), type);
02231             return 0;
02232 
02233         case INTEGER_TYPE:
02234             _assert_can_coerce(expr->type(), type,
02235                           INTEGER_TYPE, REAL_TYPE, DOUBLE_PRECISION_TYPE,
02236                           COMPLEX_TYPE, CHARACTER_TYPE);
02237 
02238             if (expr->type().data_type() == CHARACTER_TYPE)
02239                 return _coerce(expr, "ICHAR", INTEGER_TYPE, pgm);
02240             else
02241                 return _coerce(expr, "INT", INTEGER_TYPE, pgm);
02242 
02243         case REAL_TYPE:
02244             _assert_can_coerce(expr->type(), type,
02245                           INTEGER_TYPE, REAL_TYPE, DOUBLE_PRECISION_TYPE,
02246                           COMPLEX_TYPE);
02247 
02248             return _coerce(expr, "REAL", REAL_TYPE, pgm);
02249 
02250         case DOUBLE_PRECISION_TYPE:
02251             _assert_can_coerce(expr->type(), type,
02252                           INTEGER_TYPE, REAL_TYPE, DOUBLE_PRECISION_TYPE,
02253                           COMPLEX_TYPE);
02254 
02255             return _coerce(expr, "DBLE", DOUBLE_PRECISION_TYPE, pgm);
02256 
02257         case COMPLEX_TYPE:
02258             _assert_can_coerce(expr->type(), type,
02259                           INTEGER_TYPE, REAL_TYPE, DOUBLE_PRECISION_TYPE,
02260                           COMPLEX_TYPE);
02261 
02262             return _coerce(expr, "CMPLX", COMPLEX_TYPE, pgm);
02263 
02264         case CHARACTER_TYPE:
02265             _assert_can_coerce(expr->type(), type, INTEGER_TYPE);
02266 
02267             return _coerce(expr, "CHAR", CHARACTER_TYPE, pgm);
02268 
02269         default:
02270             _cannot_coerce(expr->type(), type);
02271             break;
02272         }
02273     }
02274 
02275     return 0;
02276 }
02277 
02278 //------------------------------------------------------------------------ 
02279 
02280 
02281 Listable       *
02282 Expression::listable_clone() const
02283 {
02284     return clone();
02285 }
02286 
02287 void 
02288 Expression::relink_eptrs(ProgramUnit & NOTUSED(p))
02289 {
02290     /// ...  nothing to do
02291 }
02292 
02293 int
02294 Expression::compare(const Expression & ex) const
02295 {
02296     if (op() != ex.op())
02297         return (((int) op()<(int) ex.op()) ? -1 : 1);
02298 
02299     const           Type & x = type();
02300     const           Type & y = ex.type();
02301 
02302     if (x.data_type() != y.data_type())
02303         return (((int) x.data_type()<(int) y.data_type()) ? -1 : 1);
02304 
02305     if (x.size() != y.size())
02306         return ((x.size()<y.size()) ? -1 : 1);
02307 
02308     return node_compare(ex);
02309 }
02310 
02311 int
02312 Expression::node_compare(const Expression & ex) const
02313 {
02314     if (arg_list().entries() != ex.arg_list().entries())
02315     if (arg_list().entries() > ex.arg_list().entries())
02316         return 1;
02317     else
02318         return -1;
02319     else {
02320     int    cmp = 0;
02321 
02322     Iterator<Expression> a_iter = arg_list();
02323     Iterator<Expression> b_iter = ex.arg_list();
02324     
02325     for (; a_iter.valid() && b_iter.valid(); ++a_iter, ++b_iter) 
02326         if ((cmp = a_iter.current().compare(b_iter.current())) != 0)
02327         return cmp;
02328     }
02329 
02330     return 0;
02331 }
02332 
02333 const ExprSignature &
02334 Expression::update_signature()
02335 {
02336     _signature_live().clear();
02337   
02338     _signature_live().merge( (int) op() );
02339 
02340     /// ...  Commented out the inclusion of the type in the signature so
02341     /// ...  as to speed up update_signature(), which simplify() calls a
02342     /// ...  lot.
02343 
02344     /// ...  _signature_live().merge( (int) type().data_type() );
02345     /// ...  _signature_live().merge( type().size() );
02346 
02347     for (Iterator<Expression> iter = arg_list(); iter.valid(); ++iter)
02348         _signature_live().merge( iter.current().signature() );
02349 
02350     return signature();
02351 }
02352 
02353 const ExprSignature &
02354 Expression::create_signature()
02355 {
02356     for (Iterator<Expression> iter = arg_list(); iter.valid(); ++iter) 
02357         iter.current().create_signature();
02358 
02359     update_signature();
02360 
02361     return signature();
02362 }
02363 
02364 const ExprSignature &
02365 Expression::standardize()
02366 {
02367     for (Iterator<Expression> iter = arg_list(); iter.valid(); ++iter) 
02368         iter.current().standardize();
02369 
02370     if (is_commutative(op()))
02371         _sort_expr_list(arg_list());
02372     else if (op() == INTRINSIC_CALL_OP) {
02373         const char *intr_name = intrinsic().symbol().name_ref();
02374         if (is_commutative_intrinsic_name(intr_name)) {
02375             _sort_expr_list(parameters_guarded().arg_list());
02376             parameters_guarded().update_signature();
02377         }
02378     }
02379     
02380     update_signature();
02381 
02382     return signature();
02383 }
02384 
02385 const Expression &
02386 Expression::lambda_expr() const
02387 {
02388     p_abort("const Expression &lambda_expr() const called for non-LambdaCallExpr");
02389     return DUMMY_EXPR_REF;
02390 }
02391 
02392 Expression &
02393 Expression::lambda_expr()
02394 {
02395     p_abort("Expression &lambda_expr() called for non-LambdaCallExpr");
02396     return DUMMY_EXPR_REF;
02397 }
02398 
02399 void
02400 Expression::lambda_expr(Expression *)
02401 {
02402     p_abort("void lambda_expr(Expression *) called for non-LambdaCallExpr");
02403 }
02404 
02405 Boolean
02406 Expression::args_are_non_null() const
02407 {
02408     return True;
02409 }
02410 
02411 const List<Expression> &
02412 Expression::arg_list() const
02413 {
02414     static List<Expression> *_empty_arg_list = 0; /// ...  List of no arguments
02415 
02416     if (_empty_arg_list == 0)
02417       _empty_arg_list = new List<Expression>;
02418 
02419     _empty_arg_list->fix_size();
02420 
02421     return *_empty_arg_list;
02422 }
02423 
02424 List<Expression> &
02425 Expression::arg_list()
02426 {
02427     static List<Expression> *_empty_arg_list = 0; /// ...  List of no arguments
02428 
02429     if (_empty_arg_list == 0)
02430       _empty_arg_list = new List<Expression>;
02431 
02432     _empty_arg_list->fix_size();
02433 
02434     return *_empty_arg_list;
02435 }
02436 
02437 const RefList<Expression> *
02438 Expression::arg_refs() const
02439 {
02440     return new RefList<Expression>;
02441 }
02442 
02443 
02444 
02445 /// DUMMY FUNCTIONS
02446 
02447 int
02448 Expression::value() const
02449 {
02450     _ref_error("int value() const");
02451     return 0;
02452 }
02453 
02454 void 
02455 Expression::value(int NOTUSED(v))
02456 {
02457     _ref_error("value(int v)");
02458 }
02459 
02460 const char *
02461 Expression::data_ref() const
02462 {
02463     return 0;
02464 }
02465 
02466 const String & 
02467 Expression::str_data() const
02468 {
02469     _ref_error("const String & str_data() const");
02470     return *((String *)0);
02471 }
02472 
02473 String & 
02474 Expression::str_data()
02475 {
02476     _ref_error("String & str_data()");
02477     return *((String *)0);
02478 }
02479 
02480 void 
02481 Expression::data(const char *NOTUSED(v))
02482 {
02483     _ref_error("data(const char *v)");
02484 }
02485 
02486 const Expression & 
02487 Expression::real_part() const
02488 {
02489     _ref_error("const Expression & real_part() const");
02490     return DUMMY_EXPR_REF;
02491 }
02492 
02493 Expression & 
02494 Expression::real_part()
02495 {
02496     _ref_error("Expression & real_part()");
02497     return DUMMY_EXPR_REF;
02498 }
02499 
02500 void 
02501 Expression::real_part(Expression * NOTUSED(e))
02502 {
02503     _ref_error("real_part(Expression* e)");
02504 }
02505 
02506 const Expression & 
02507 Expression::imaginary_part() const
02508 {
02509     _ref_error("const Expression & imaginary_part() const");
02510     return DUMMY_EXPR_REF;
02511 }
02512 
02513 Expression & 
02514 Expression::imaginary_part()
02515 {
02516     _ref_error("Expression & imaginary_part()");
02517     return DUMMY_EXPR_REF;
02518 }
02519 
02520 void 
02521 Expression::imaginary_part(Expression * NOTUSED(e))
02522 {
02523     _ref_error("imaginary_part(Expression* e)");
02524 }
02525 
02526 const Expression & 
02527 Expression::array() const
02528 {
02529     _ref_error("const Expression & array() const");
02530     return DUMMY_EXPR_REF;
02531 } 
02532 
02533 Expression & 
02534 Expression::array()
02535 {
02536     _ref_error("Expression & array()");
02537     return DUMMY_EXPR_REF;
02538 } 
02539 
02540 void 
02541 Expression::array(Expression * NOTUSED(e))
02542 {
02543     _ref_error("array(Expression* e)");
02544 }
02545 
02546 const Expression & 
02547 Expression::subscript() const
02548 {
02549     _ref_error("const Expression & subscript() const");
02550     return DUMMY_EXPR_REF;
02551 }
02552 
02553 Expression & 
02554 Expression::subscript()
02555 {
02556     _ref_error("Expression & subscript()");
02557     return DUMMY_EXPR_REF;
02558 }
02559 
02560 void 
02561 Expression::subscript(Expression * NOTUSED(e))
02562 {
02563     _ref_error("subscript(Expression* e)");
02564 }
02565 
02566 const Expression & 
02567 Expression::string() const
02568 {
02569     _ref_error("const Expression & string() const");
02570     return DUMMY_EXPR_REF;
02571 }
02572 
02573 Expression & 
02574 Expression::string()
02575 {
02576     _ref_error("Expression & string()");
02577     return DUMMY_EXPR_REF;
02578 }
02579 
02580 void 
02581 Expression::string(Expression * NOTUSED(e))
02582 {
02583     _ref_error("string(Expression* e)");
02584 }
02585 
02586 const Expression & 
02587 Expression::bound() const
02588 {
02589     _ref_error("const Expression & bound() const");
02590     return DUMMY_EXPR_REF;
02591 }
02592 
02593 Expression & 
02594 Expression::bound()
02595 {
02596     _ref_error("Expression & bound()");
02597     return DUMMY_EXPR_REF;
02598 }
02599 
02600 void 
02601 Expression::bound(Expression * NOTUSED(e))
02602 {
02603     _ref_error("bound(Expression* e)");
02604 }
02605 
02606 const Expression & 
02607 Expression::left_guarded() const
02608 {
02609     _ref_error("const Expression & left_guarded() const");
02610     return DUMMY_EXPR_REF;
02611 }
02612 
02613 Expression & 
02614 Expression::left_guarded()
02615 {
02616     _ref_error("Expression & left_guarded()");
02617     return DUMMY_EXPR_REF;
02618 }
02619 
02620 void 
02621 Expression::left(Expression * NOTUSED(e))
02622 {
02623     _ref_error("left(Expression* e)");
02624 } 
02625 
02626 Boolean 
02627 Expression::left_valid() const
02628 {
02629     return False;
02630 };
02631 
02632 Expression *
02633 Expression::grab_left()
02634 {
02635     _ref_error("Expression * grab_left()");
02636     return 0;
02637 }
02638 
02639 const Expression & 
02640 Expression::right_guarded() const
02641 {
02642     _ref_error("const Expression & right_guarded() const");
02643     return DUMMY_EXPR_REF;
02644 } 
02645 
02646 Expression & 
02647 Expression::right_guarded()
02648 {
02649     _ref_error("Expression & right_guarded()");
02650     return DUMMY_EXPR_REF;
02651 } 
02652 
02653 void 
02654 Expression::right(Expression * NOTUSED(e))
02655 {
02656     _ref_error("right(Expression* e)");
02657 } 
02658 
02659 Boolean 
02660 Expression::right_valid() const
02661 {
02662     return False;
02663 }
02664 
02665 Expression *
02666 Expression::grab_right()
02667 {
02668     _ref_error("Expression * grab_right()");
02669     return 0;
02670 }
02671 
02672 const Expression & 
02673 Expression::function() const
02674 {
02675     _ref_error("const Expression & function() const");
02676     return DUMMY_EXPR_REF;
02677 }
02678 
02679 Expression & 
02680 Expression::function()
02681 {
02682     _ref_error("Expression & function()");
02683     return DUMMY_EXPR_REF;
02684 }
02685 
02686 void 
02687 Expression::function(Expression * NOTUSED(e))
02688 {
02689     _ref_error("function(Expression* e)");
02690 }
02691 
02692 const Expression & 
02693 Expression::parameters_guarded() const
02694 {
02695     _ref_error("const Expression & parameters_guarded() const");
02696     return DUMMY_EXPR_REF;
02697 }
02698 
02699 Expression & 
02700 Expression::parameters_guarded()
02701 {
02702     _ref_error("Expression & parameters_guarded()");
02703     return DUMMY_EXPR_REF;
02704 }
02705 
02706 void 
02707 Expression::parameters(Expression * NOTUSED(e))
02708 {
02709     _ref_error("parameters(Expression* e)");
02710 } 
02711 
02712 Boolean 
02713 Expression::parameters_valid() const
02714 {
02715     return False;
02716 }
02717 
02718 const Expression & 
02719 Expression::expr_guarded() const
02720 {
02721     _ref_error("const Expression & expr_guarded() const");
02722     return DUMMY_EXPR_REF;
02723 } 
02724 
02725 Expression & 
02726 Expression::expr_guarded()
02727 {
02728     _ref_error("Expression & expr_guarded()");
02729     return DUMMY_EXPR_REF;
02730 } 
02731 
02732 void 
02733 Expression::expr(Expression * NOTUSED(e))
02734 {
02735     _ref_error("expr(Expression* e)");
02736 } 
02737 
02738 Boolean 
02739 Expression::expr_valid() const
02740 {
02741     return False;
02742 }
02743 
02744 Expression *
02745 Expression::grab_expr()
02746 {
02747     _ref_error("Expression * grab_expr()");
02748     return 0;
02749 }
02750 
02751 const Symbol & 
02752 Expression::symbol() const
02753 {
02754     _ref_error("const Symbol & symbol() const");
02755     return *((const Symbol *) 0);
02756 }
02757 
02758 Symbol & 
02759 Expression::symbol()
02760 {
02761     _ref_error("Symbol & symbol()");
02762     return *((Symbol *) 0);
02763 }
02764 
02765 void 
02766 Expression::symbol(const Symbol & NOTUSED(s))
02767 {
02768     _ref_error("symbol(Symbol & s)");
02769 }
02770 
02771 const Expression & 
02772 Expression::substituted_guarded() const
02773 {
02774     _ref_error("const Expression & substituted_guarded() const");
02775     return DUMMY_EXPR_REF;
02776 } 
02777 
02778 Expression & 
02779 Expression::substituted_guarded() 
02780 {
02781     _ref_error("Expression & substituted_guarded()");
02782     return DUMMY_EXPR_REF;
02783 } 
02784 
02785 void 
02786 Expression::substituted(Expression * NOTUSED(e))
02787 {
02788     _ref_error("substituted(Expression* e)");
02789 } 
02790 
02791 Boolean 
02792 Expression::substituted_valid() const
02793 {
02794     return False;
02795 }
02796 
02797 Expression *
02798 Expression::grab_substituted()
02799 {
02800     _ref_error("Expression * grab_substituted() const");
02801     return 0;
02802 }
02803 
02804 const Expression & 
02805 Expression::iolist() const
02806 {
02807     _ref_error("const Expression & iolist() const");
02808     return DUMMY_EXPR_REF;
02809 } 
02810 
02811 Expression & 
02812 Expression::iolist()
02813 {
02814     _ref_error("Expression & iolist()");
02815     return DUMMY_EXPR_REF;
02816 } 
02817 
02818 void 
02819 Expression::iolist(Expression * NOTUSED(e))
02820 {
02821     _ref_error("iolist(Expression* e)");
02822 }
02823 
02824 const Expression & 
02825 Expression::iterator() const
02826 {
02827     _ref_error("const Expression & iterator() const");
02828     return DUMMY_EXPR_REF;
02829 } 
02830 
02831 Expression & 
02832 Expression::iterator()
02833 {
02834     _ref_error("Expression & iterator()");
02835     return DUMMY_EXPR_REF;
02836 } 
02837 
02838 void 
02839 Expression::iterator(Expression * NOTUSED(e))
02840 {
02841 
02842     _ref_error("iterator(Expression* e)");
02843 }
02844 
02845 const Expression & 
02846 Expression::index_id() const
02847 {
02848     _ref_error("const Expression & index_id() const");
02849     return DUMMY_EXPR_REF;
02850 } 
02851 
02852 Expression & 
02853 Expression::index_id()
02854 {
02855     _ref_error("Expression & index_id()");
02856     return DUMMY_EXPR_REF;
02857 } 
02858 
02859 void 
02860 Expression::index_id(Expression * NOTUSED(e))
02861 {
02862     _ref_error("index_id(Expression* e)");
02863 }
02864 
02865 const Expression & 
02866 Expression::iteration_space() const
02867 {
02868     _ref_error("const Expression & iteration_space() const");
02869     return DUMMY_EXPR_REF;
02870 } 
02871 
02872 Expression & 
02873 Expression::iteration_space()
02874 {
02875     _ref_error("Expression & iteration_space()");
02876     return DUMMY_EXPR_REF;
02877 } 
02878 
02879 void 
02880 Expression::iteration_space(Expression * NOTUSED(e))
02881 {
02882 
02883     _ref_error("iteration_space(Expression* e)");
02884 }
02885 
02886 const Expression & 
02887 Expression::intrinsic() const
02888 {
02889     _ref_error("const Expression & intrinsic() const");
02890     return DUMMY_EXPR_REF;
02891 } 
02892 
02893 Expression & 
02894 Expression::intrinsic() 
02895 {
02896     _ref_error("Expression & intrinsic()");
02897     return DUMMY_EXPR_REF;
02898 } 
02899 
02900 void 
02901 Expression::intrinsic(Expression * NOTUSED(e))
02902 {
02903     _ref_error("intrinsic(Expression* e)");
02904 }
02905 
02906 int 
02907 Expression::entry() const
02908 {
02909     _ref_error("int entry() const");
02910     return 0;
02911 }
02912 
02913 void 
02914 Expression::entry(int NOTUSED(e))
02915 {
02916     _ref_error("entry(int e)");
02917 }
02918 
02919 const Format & 
02920 Expression::format() const
02921 {
02922     _ref_error("const Format & format() const");
02923     return *((const Format *) 0);
02924 }
02925 
02926 Format & 
02927 Expression::format()
02928 {
02929     _ref_error("Format & format()");
02930     return *((Format *) 0);
02931 }
02932 
02933 void 
02934 Expression::format(Format & NOTUSED(format))
02935 {
02936     _ref_error("format(Format & format)");
02937 }
02938 
02939 const Statement & 
02940 Expression::stmt() const
02941 {
02942     _ref_error("const Statement & stmt() const");
02943     return *((const Statement *) 0);
02944 }
02945 
02946 Statement & 
02947 Expression::stmt()
02948 {
02949     _ref_error("Statement & stmt()");
02950     return *((Statement *) 0);
02951 }
02952 
02953 void 
02954 Expression::stmt(Statement & NOTUSED(stmt))
02955 {
02956     _ref_error("stmt(Statement & stmt)");
02957 }
02958 
02959 int
02960 Expression::sign() const
02961 {
02962     _ref_error("int sign() const");
02963     return 0;
02964 }
02965 
02966 void 
02967 Expression::sign(int NOTUSED(s))
02968 {
02969     _ref_error("sign(int s)");
02970 }
02971 
02972 const Expression & 
02973 Expression::gate() const
02974 {
02975     _ref_error("const Expression & gate() const");
02976     return DUMMY_EXPR_REF;
02977 } 
02978 
02979 Expression & 
02980 Expression::gate()
02981 {
02982     _ref_error("Expression & gate()");
02983     return DUMMY_EXPR_REF;
02984 } 
02985 
02986 void 
02987 Expression::gate(Expression * NOTUSED(e))
02988 {
02989     _ref_error("gate(Expression* e)");
02990 }
02991 
02992 /// This print function is to satisfy Listable::print(...)
02993 
02994 void
02995 Expression::print(ostream & o) const
02996 {
02997     print_debug(o, subst_field_print);
02998 }
02999 
03000 ostream &
03001 operator << (ostream & o, const Expression & e) 
03002 {
03003     e.print_debug(o, subst_field_print);
03004 
03005     if (e._overflow)
03006         o << "{" << *(e._overflow) << "}";
03007 
03008     return o;
03009 }
03010 
03011 /// tableEntry takes an integer and returns a pointer to an Expression
03012 /// object which represents another entry in the expression table.  This
03013 /// intermediate table-entry expression object is an intermediate form
03014 /// which is only used in converting expressions from table form to
03015 /// expression object form and should not be used to represent actual
03016 /// expressions.
03017 
03018 Expression     *
03019 Expression::tableEntry(int n)
03020 {
03021     Expression     *t = new TableExpr(n);
03022 
03023     return t;
03024 }
03025 
03026 /// Helper function: used to get the type field.
03027 
03028 void
03029 Expression::get_type(BinRep & typebin, const char *exprname)
03030 {
03031     if (!typebin.is_string()) {
03032         cerr << exprname
03033              << "Expr::convert: type field doesn't contain string\n";
03034         p_abort("(See above error message)");
03035     }
03036 
03037     String          s;
03038 
03039     typebin.to_string(s);
03040 
03041     if (s == "INTEGER")
03042         type(make_type(INTEGER_TYPE));
03043     else if (s == "REAL")
03044         type(make_type(REAL_TYPE));
03045     else if (s == "DOUBLE PRECISION")
03046         type(make_type(DOUBLE_PRECISION_TYPE));
03047     else if (s == "CHARACTER")
03048         type(make_type(CHARACTER_TYPE));
03049     else if (s == "COMPLEX")
03050         type(make_type(COMPLEX_TYPE));
03051     else if (s == "LOGICAL")
03052         type(make_type(LOGICAL_TYPE));
03053     else if (s == "VOID")
03054         type(make_type(VOID_TYPE));
03055     else {
03056         cerr << exprname
03057              << "Expr::convert:  Unrecognized string in 'type' field: "
03058              << s << endl;
03059         p_abort("(See above error message)");
03060     }
03061 }
03062 
03063 /// Helper function: insert leftovers into the overflow
03064 
03065 void
03066 Expression::make_overflow(Iterator<BinRep> & iter, const char *exname)
03067 {
03068     warn_overflow_map(exname, iter.current());
03069 
03070     if (!_overflow) {
03071         _overflow = new BinRep;
03072         Set<BinRep> *S = new Set<BinRep>;
03073         _overflow->put_set( S );
03074     }
03075 
03076     _overflow->ins(iter.current());
03077 }
03078 
03079 /// Helper function:  Make sure overflow is empty
03080 
03081 void
03082 Expression::empty_overflow()
03083 {
03084     if (_overflow)
03085         delete _overflow;
03086 
03087     _overflow = 0;
03088 }
03089 
03090 int     
03091 Expression::exchange_expr( VDL & vdl )
03092 {
03093     int index = vdl.look_up_expr( *this );
03094 
03095     if (index >= 0)
03096         return index;
03097 
03098     BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03099     BinRep  *br = new BinRep( new Set<BinRep> );
03100 
03101     List<BinRep> & L = b->find_ref( "expression" )->to_tuple();
03102 
03103     L.ins_last( br );
03104 
03105     BinRep  *bs = new BinRep( new List<BinRep> );
03106     bs->to_tuple().ins_last(new BinRep( "type" ));
03107     bs->to_tuple().ins_last(new BinRep( this->type().name_ref() ));
03108     br->to_set().ins( bs );
03109 
03110     bs->to_tuple().ins_last(new BinRep( "size" ));
03111     bs->to_tuple().ins_last(new BinRep( this->type().size() ));
03112     br->to_set().ins( bs );
03113 
03114     index = L.entries();
03115 
03116     vdl.install_expr( *this, index );
03117 
03118     return index;
03119 }
03120 
03121 /// Function used for writing expressions, specifies Fortran 77
03122 /// operator-precedence
03123 
03124 int
03125 operator_precedence(const OP_TYPE ot)
03126 {
03127     switch (ot) {
03128     case PAREN_OP:
03129     case LAMBDA_CALL_OP:
03130     case ARG_OP:
03131         return 0;
03132 
03133     case U_PLUS_OP:
03134     case U_MINUS_OP:
03135     case SUB_OP:
03136     case ADD_OP:
03137         return 70;
03138 
03139     case NOT_OP:
03140         return 40;
03141 
03142     case EQ_OP:
03143     case GE_OP:
03144     case NE_OP:
03145     case LT_OP:
03146     case LE_OP:
03147     case GT_OP:
03148         return 50;
03149 
03150     case DIV_OP:
03151     case INTDIV_OP:
03152     case RATDIV_OP:
03153     case MULT_OP:
03154         return 80;
03155 
03156     case EXP_OP:
03157         return 90;
03158 
03159     case CONCAT_OP:
03160         return 60;
03161 
03162     case OR_OP:
03163         return 20;
03164 
03165     case AND_OP:
03166         return 30;
03167 
03168     case EQV_OP:
03169     case NEQV_OP:
03170         return 10;
03171 
03172     case COMMA_OP:
03173         return 1;
03174 
03175     default:
03176         return -1;
03177     }
03178 }
03179 
03180 /// print the expression to \'o\', parenthesizing if the precedence
03181 /// calls for it.
03182 
03183 void
03184 print_prec(OP_TYPE parent_op, const Expression * e, ostream & o)
03185 {
03186     if (!e)
03187         o << "<UNDEFINED>";
03188     else {
03189         int             e_prec = operator_precedence(e->op());
03190         int             our_prec = operator_precedence(parent_op);
03191         Boolean         print_with_paren = False;
03192 
03193         if (e_prec != -1 && our_prec != -1
03194             && (e_prec < our_prec
03195                 || (e_prec == our_prec 
03196                     && (e->op() != COMMA_OP)
03197                     && (1 || parent_op == EXP_OP
03198                           || parent_op == U_MINUS_OP
03199                           || parent_op == U_PLUS_OP)))) {
03200             print_with_paren = True;
03201         }
03202 
03203         switch (e->op()) {
03204         case INTEGER_CONSTANT_OP:
03205             if (e->value()<0)
03206                 print_with_paren = True;
03207             break;
03208         case REAL_CONSTANT_OP:
03209             if (e->data_ref()[0] == '-')
03210                 print_with_paren = True;
03211             break;
03212         default:
03213             /// ...  do nothing
03214             break;
03215         }
03216 
03217         if (!print_with_paren && dbx_full_parenthesization) {
03218             /// ...  Override and ADD parentheses only if the following
03219             /// ...  cases hold.  (Pretty much things that are leaves
03220             /// ...  don't want parentheses for aesthetic and syntax reasons).
03221 
03222             if (!e->is_wildcard()) {
03223                 switch (e->op()) {
03224                 default:
03225                     /// ...  DO override for anything not specifically specified
03226                     print_with_paren = True;
03227                     break;
03228 
03229                 case INTEGER_CONSTANT_OP:
03230                 case REAL_CONSTANT_OP:
03231                 case STRING_CONSTANT_OP:
03232                 case LOGICAL_CONSTANT_OP:
03233                 case HOLLERITH_CONSTANT_OP:
03234                 case ARRAY_REF_OP:
03235                 case SUBSTRING_OP:
03236                 case FUNCTION_CALL_OP:
03237                 case INTRINSIC_CALL_OP:
03238                 case LAMBDA_CALL_OP:
03239                 case ARG_OP:
03240                 case RETURN_OP:
03241                 case LABEL_OP:
03242                 case IO_STAR_OP:
03243                 case FORMAT_OP:
03244                 case ID_OP:
03245                 case KEY_OP:
03246                 case KEYPAIR_OP:
03247                 case DO_OP:
03248                 case EQUAL_OP:
03249                 case COMMA_OP:
03250                     /// ...  DON'T OVERRIDE FOR THESE LEAF-TYPES
03251                     break;
03252                 }
03253             }
03254         }
03255 
03256         if (print_with_paren)
03257             o << "(" << *e << ")";
03258         else
03259             o << *e;
03260     }
03261 }
03262 
03263 /// Helper function used to print the given list, sepperating each
03264 /// element by c. ot is op_type of parent expr.
03265 
03266 void
03267 print_prec_list(ostream & o, OP_TYPE optype, const List<Expression> &l, 
03268                 const char *c)
03269 {
03270     Iterator<Expression> iter = l;
03271     
03272     if (iter.end()) {
03273         /// ...  An empty COLON list is meaningful.  i.e.  A(:)
03274         if (optype == COLON_OP)
03275             o << c;
03276     }
03277     else {
03278         print_prec(optype, &iter.current(), o);
03279         iter.next();
03280     
03281         if (iter.end()) {
03282             /// ...  An single element COLON list is meaningful.  i.e.  A(5:)
03283             if (optype == COLON_OP)
03284                 o << c;
03285         }
03286         else {
03287             for ( ; !iter.end(); iter.next()) {
03288                 o << c;
03289                 print_prec(optype, &iter.current(), o);
03290             }
03291         }
03292     }
03293 }
03294 
03295 //-----------------------------------------------------------------------------
03296 /// ArgNumberExpr code:
03297 ///
03298 
03299 ArgNumberExpr::~ArgNumberExpr() 
03300 {
03301     /// ...  nothing to do
03302 }
03303 
03304 ArgNumberExpr &
03305 ArgNumberExpr::operator = (const ArgNumberExpr & e) 
03306 {
03307     if (this != &e)
03308         _value = e.value();
03309 
03310     return *this;
03311 }
03312 
03313 Expression     *
03314 ArgNumberExpr::clone() const
03315 {
03316     return new ArgNumberExpr(*this);
03317 }
03318 
03319 int
03320 ArgNumberExpr::structures_OK() const
03321 {
03322     cerr << "ArgNumber::structures_OK() not implemented";
03323     return True;
03324 }
03325  
03326 int     
03327 ArgNumberExpr::exchange_expr( VDL & vdl )
03328 {
03329     int index = vdl.look_up_expr( *this );
03330 
03331     if (index >= 0)
03332         return index;
03333 
03334     index = Expression::exchange_expr( vdl );
03335 
03336     BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03337 
03338     Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
03339 
03340     BinRep  *br = new BinRep( new List<BinRep> );
03341     br->to_tuple().ins_last(new BinRep( "op" ));
03342     br->to_tuple().ins_last(new BinRep( "ARG#" ));
03343     S.ins( br );
03344 
03345     br = new BinRep( new List<BinRep> );
03346     br->to_tuple().ins_last(new BinRep( "data" ));
03347     br->to_tuple().ins_last(new BinRep( this->value() ));
03348 
03349     return index;
03350 }
03351 
03352 void
03353 ArgNumberExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
03354 {
03355     String          s;
03356     BinRep      second;     /// ...  The second argument of tuple pairs
03357 
03358     empty_overflow();
03359 
03360     for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
03361                           expr_iter.valid(); ++expr_iter) {
03362         String          field;
03363 
03364         expr_iter.current()[0].to_string(field);
03365         second = expr_iter.current()[1];
03366 
03367         if (field == "type")
03368             get_type(second, "ArgNumber");
03369         else if (field == "data") {
03370             p_assert( second.is_integer(), "ArgNumber::convert: "
03371                       "'data' field does not contain an int." );
03372             _value = second.to_integer();
03373         }
03374         else if (field != "op" && field != "size")
03375             make_overflow(expr_iter, "ArgNumber");
03376     }
03377 }
03378 
03379 void
03380 ArgNumberExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
03381 {
03382     o << "#" << _value;
03383 }
03384 
03385 //-----------------------------------------------------------------------------
03386 /// ArrayRefExpr code:
03387 ///
03388 
03389 /// Note: The following data fields are aliased:
03390 /// array = left
03391 /// subscript = right
03392 
03393 ArrayRefExpr::~ArrayRefExpr() 
03394 {
03395     if (_arcs)
03396        delete _arcs;
03397 }
03398 
03399 Expression     *
03400 ArrayRefExpr::clone() const
03401 {
03402     return new ArrayRefExpr(*this);
03403 }
03404 
03405 ArrayRefExpr &
03406 ArrayRefExpr::operator = (const ArrayRefExpr & e) 
03407 {
03408     if (this != &e) {
03409         BinaryExpr::operator = (e);
03410         _arcs = 0;
03411     }
03412 
03413     return *this;
03414 }
03415 
03416 void 
03417 ArrayRefExpr::array(Expression * e)
03418 {
03419   p_assert(e->op() == ID_OP,
03420        "ArrayRefExpr::array( ) expression not an IDExpr");
03421   _left(e);
03422 }
03423 
03424 void
03425 ArrayRefExpr::subscript(Expression * e)
03426 {
03427     p_assert(e->op() == COMMA_OP,
03428              "ArrayRefExpr::subscript( ) expression not an CommaExpr");
03429     _right(e);
03430 }
03431 
03432 int
03433 ArrayRefExpr::structures_OK() const
03434 {
03435     cerr << "ArrayRefExpr::structures_OK() not implemented";
03436     return True;
03437 }
03438 
03439 int     
03440 ArrayRefExpr::exchange_expr( VDL & vdl )
03441 {
03442     int index = vdl.look_up_expr( *this );
03443 
03444     if (index >= 0)
03445         return index;
03446 
03447     index = Expression::exchange_expr( vdl );
03448 
03449     BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03450 
03451     Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
03452 
03453     BinRep  *br = new BinRep( new List<BinRep> );
03454     br->to_tuple().ins_last(new BinRep( "op" ));
03455     br->to_tuple().ins_last(new BinRep( "ARRAY_REF" ));
03456     S.ins( br );
03457 
03458     br = new BinRep( new List<BinRep> );
03459     br->to_tuple().ins_last(new BinRep( "args" ));
03460     BinRep  *bt = new BinRep(new List<BinRep>);
03461     br->to_tuple().ins_last( bt );
03462     S.ins( br );
03463 
03464 
03465     bt->to_tuple().ins_last(
03466         new BinRep( this->array().exchange_expr(vdl)));
03467     bt->to_tuple().ins_last(
03468         new BinRep( this->subscript().exchange_expr(vdl)));
03469 
03470     return index;
03471 }
03472 
03473 void
03474 ArrayRefExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
03475 {
03476     String          s;
03477     BinRep      second;     /// ...  The second argument of tuple pairs
03478 
03479     empty_overflow();
03480 
03481     for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
03482                           expr_iter.valid(); ++expr_iter) {
03483         String          field;
03484 
03485         expr_iter.current()[0].to_string(field);
03486         second = expr_iter.current()[1];
03487 
03488         if (field == "type")
03489             get_type(second, "ArrayRef");
03490         else if (field == "size") {
03491             p_assert( second.is_integer(), "ArrayRefExpr::convert: "
03492                       "'size' field contains non-int." );
03493             _type.set(second.to_integer());
03494         }
03495         else if (field == "args") {
03496             Iterator<BinRep>  iter = second.to_tuple();
03497             BinRep            theArg = iter.current();
03498 
03499             /// ...  first element of args tuple
03500 
03501             Expression     *e1;
03502 
03503             p_assert( theArg.is_integer(),
03504                       "ArrayRefExpr::convert: arg field contains non-int." );
03505 
03506             e1 = tableEntry(theArg.to_integer());
03507 
03508             ++iter;
03509 
03510             theArg = iter.current();    /// ...  Second element of args tuple
03511 
03512             p_assert( theArg.is_integer(),
03513                       "ArrayRefExpr::convert: arg field contains non-int." );
03514 
03515             Expression     *e2 = tableEntry(theArg.to_integer());
03516 
03517             _left(e1);
03518             _right(e2);
03519         }
03520         else if (field != "op" && field != "size")
03521             make_overflow(expr_iter, "ArrayRefExpr");
03522     }
03523 }
03524 
03525 void
03526 ArrayRefExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
03527 {
03528     print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
03529     o << "(";
03530     print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
03531     o << ")";
03532 }
03533 
03534 //-----------------------------------------------------------------------------
03535 /// BinaryExpr code:
03536 ///
03537 
03538 BinaryExpr::~BinaryExpr() 
03539 {
03540     /// ...  nothing to do
03541 }
03542 
03543 Expression     *
03544 BinaryExpr::clone() const
03545 {
03546     return new BinaryExpr(*this);
03547 }
03548 
03549 BinaryExpr &
03550 BinaryExpr::operator = (const BinaryExpr & e) 
03551 {
03552     if (this != &e) {
03553         if (e._left_valid())
03554             _left(e._left_guarded().clone());
03555         else
03556             _left(0);
03557 
03558         if (e._right_valid())
03559             _right(e._right_guarded().clone());
03560         else
03561             _right(0);
03562     }
03563 
03564     return *this;
03565 }
03566 
03567 const RefList<Expression>*
03568 BinaryExpr::arg_refs() const
03569 {
03570     RefList<Expression>*args = new RefList<Expression>;
03571 
03572     if (_left_valid())
03573         args->ins_last(CASTAWAY(Expression &) _left_guarded());
03574 
03575     if (_right_valid())
03576         args->ins_last(CASTAWAY(Expression &) _right_guarded());
03577 
03578     return (const RefList<Expression> *) args;
03579 }
03580 
03581 void 
03582 BinaryExpr::left(Expression * e) 
03583 {
03584     _left(e);
03585 }
03586 
03587 const Expression & 
03588 BinaryExpr::left_guarded() const 
03589 {
03590     return _left_guarded();
03591 }
03592 
03593 Expression & 
03594 BinaryExpr::left_guarded()
03595 {
03596     return _left_guarded();
03597 }
03598 
03599 Boolean
03600 BinaryExpr::left_valid() const 
03601 {
03602     return _left_valid();
03603 }
03604 
03605 Expression *
03606 BinaryExpr::grab_left()
03607 {
03608     return _grab_left();
03609 }
03610 
03611 void
03612 BinaryExpr::right(Expression * e) 
03613 {
03614     _right(e);
03615 }
03616 
03617 const Expression & 
03618 BinaryExpr::right_guarded() const 
03619 {
03620     return _right_guarded();
03621 }
03622 
03623 Expression & 
03624 BinaryExpr::right_guarded()
03625 {
03626     return _right_guarded();
03627 }
03628 
03629 Boolean
03630 BinaryExpr::right_valid() const 
03631 {
03632     return _right_valid();
03633 }
03634 
03635 Expression *
03636 BinaryExpr::grab_right()
03637 {
03638     return _grab_right();
03639 }
03640 
03641 Boolean
03642 BinaryExpr::args_are_non_null() const
03643 {
03644     return _left_valid() && _right_valid();
03645 }
03646 
03647 const List<Expression> &
03648 BinaryExpr::arg_list() const
03649 {
03650     return _arg_list;
03651 }
03652 
03653 List<Expression> &
03654 BinaryExpr::arg_list()
03655 {
03656     return _arg_list;
03657 }
03658 
03659 int
03660 BinaryExpr::structures_OK() const
03661 {
03662     cerr << "BinaryExpr::structures_OK() not implemented";
03663     return True;
03664 }
03665 
03666 int     
03667 BinaryExpr::exchange_expr( VDL & vdl )
03668 {
03669     int index = vdl.look_up_expr( *this );
03670 
03671     if (index >= 0)
03672         return index;
03673 
03674     index = Expression::exchange_expr( vdl );
03675 
03676     BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03677 
03678     Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
03679 
03680     String opcode;
03681 
03682     switch (op()) {
03683     case EQ_OP:         opcode = ".EQ.";    break;
03684     case NE_OP:         opcode = ".NE.";    break;
03685     case LT_OP:         opcode = ".LT.";    break;
03686     case LE_OP:         opcode = ".LE.";    break;
03687     case GT_OP:         opcode = ".GT.";    break;
03688     case GE_OP:         opcode = ".GE.";    break;
03689     case SUB_OP:        opcode = "-";       break;
03690     case DIV_OP:        opcode = "/";       break;
03691     case INTDIV_OP:     opcode = "/#";      break;
03692     case RATDIV_OP:     opcode = "/%";      break;
03693     case EXP_OP:        opcode = "**";      break;
03694     case CONCAT_OP:     opcode = "/// ... ";      break;
03695     case REPSTAR_OP:    opcode = "REP*";    break; 
03696     case KEYPAIR_OP:    opcode = "KEYPAIR"; break;
03697     default: break;
03698     }
03699 
03700     BinRep  *br = new BinRep( new List<BinRep> );
03701     br->to_tuple().ins_last(new BinRep( "op" ));
03702     br->to_tuple().ins_last(new BinRep( opcode ));
03703     S.ins( br );
03704 
03705     br = new BinRep( new List<BinRep> );
03706     br->to_tuple().ins_last(new BinRep( "args" ));
03707     BinRep  *bt = new BinRep(new List<BinRep>);
03708     br->to_tuple().ins_last( bt );
03709     S.ins( br );
03710 
03711     bt->to_tuple().ins_last(
03712         new BinRep( this->left_guarded().exchange_expr(vdl)));
03713     bt->to_tuple().ins_last(
03714         new BinRep( this->right_guarded().exchange_expr(vdl)));
03715 
03716     return index;
03717 }
03718 
03719 
03720 void
03721 BinaryExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
03722 {
03723     String          s;
03724     BinRep      second;     /// ...  The second argument of tuple pairs
03725 
03726     empty_overflow();
03727 
03728     for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
03729                           expr_iter.valid(); ++expr_iter) {
03730         String          field;
03731 
03732         expr_iter.current()[0].to_string(field);
03733         second = expr_iter.current()[1];
03734 
03735         if (field == "type")
03736          get_type(second, "Binary");
03737      else if (field == "args") {
03738          Iterator<BinRep>      iter = second.to_tuple();
03739          BinRep      theArg = iter.current();
03740 
03741          /// ...  first element of args tuple
03742 
03743          Expression     *e1 = NULL;
03744 
03745          if (theArg.is_integer())
03746          e1 = tableEntry(theArg.to_integer());
03747          else if (theArg.is_omega())
03748          e1 = new OmegaExpr;
03749          else {
03750          p_abort( "BinaryExpr::convert: arg field contains non-int");
03751          }
03752 
03753          ++iter;
03754 
03755          theArg = iter.current();    /// ...  Second element of args tuple
03756 
03757          p_assert( theArg.is_integer(),
03758                "BinaryExpr::convert: arg field contains non-int." );
03759 
03760          Expression     *e2 = tableEntry(theArg.to_integer());
03761 
03762          _left(e1);
03763          _right(e2);
03764      }
03765      else if (field == "size") {
03766          p_assert( second.is_integer(),
03767                "BinaryExpr::convert: 'size' field contains non-int.");
03768          _type.set(second.to_integer());
03769      }
03770      else if (field != "op")
03771          make_overflow(expr_iter, "BinaryExpr");
03772      }
03773  }
03774 
03775  void
03776  BinaryExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
03777  {
03778      print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
03779 
03780      switch (op()) {
03781      case EQ_OP:
03782      o << ".EQ.";
03783      break;
03784      case NE_OP:
03785      o << ".NE.";
03786      break;
03787      case LT_OP:
03788      o << ".LT.";
03789      break;
03790      case LE_OP:
03791      o << ".LE.";
03792      break;
03793      case GT_OP:
03794      o << ".GT.";
03795      break;
03796      case GE_OP:
03797      o << ".GE.";
03798      break;
03799      case SUB_OP:
03800      o << "-";
03801      break;
03802      case DIV_OP:
03803      o << "/";
03804      break;
03805      case INTDIV_OP:
03806      o << "/#";
03807      break;
03808      case RATDIV_OP:
03809      o << "/%";
03810      break;
03811      case EXP_OP:
03812      o << "**";
03813      break;                  /// ...  precedence different
03814 
03815      case REPSTAR_OP:
03816      o << " * ";
03817      break;
03818 
03819      case KEYPAIR_OP:
03820      o << "=";
03821      break;
03822      default:
03823      break;
03824      }
03825 
03826      if (_right_valid()
03827      && (op() == SUB_OP
03828          || op() == DIV_OP
03829          || op() == INTDIV_OP
03830          || op() == RATDIV_OP)
03831      && (operator_precedence(op()) == operator_precedence(_right_guarded().op())))
03832      o << "(" << _right_guarded() << ")";
03833      else
03834      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
03835  }
03836 
03837  void 
03838  BinaryExpr::relink_eptrs(ProgramUnit & p)
03839  {
03840      if (_left_valid())
03841      _left_guarded().relink_eptrs(p);
03842 
03843      if (_right_valid())
03844      _right_guarded().relink_eptrs(p);
03845  }
03846 
03847  //-----------------------------------------------------------------------------
03848 /// CommaExpr code:
03849 ///
03850 
03851  CommaExpr::~CommaExpr()
03852  {
03853      /// ...  nothing to do
03854  }
03855 
03856  Expression     *
03857  CommaExpr::clone() const
03858  {
03859      return new CommaExpr(*this);
03860  }
03861 
03862  CommaExpr &
03863  CommaExpr::operator = (const CommaExpr & e) 
03864  {
03865      NonBinaryExpr::operator = (e);
03866 
03867      return *this;
03868  }
03869 
03870  int
03871  CommaExpr::structures_OK() const
03872  {
03873      cerr << "CommaExpr::structures_OK() not implemented";
03874      return True;
03875  }
03876 
03877  int     
03878  CommaExpr::exchange_expr( VDL & vdl )
03879  {
03880      int index = vdl.look_up_expr( *this );
03881 
03882      if (index >= 0)
03883      return index;
03884 
03885      index = Expression::exchange_expr( vdl );
03886 
03887      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03888 
03889      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
03890 
03891      BinRep  *br = new BinRep( new List<BinRep> );
03892      br->to_tuple().ins_last(new BinRep( "op" ));
03893      br->to_tuple().ins_last(new BinRep( "," ));
03894      S.ins( br );
03895 
03896      br = new BinRep( new List<BinRep> );
03897      br->to_tuple().ins_last(new BinRep( "args" ));
03898      BinRep  *bt = new BinRep(new List<BinRep>);
03899      br->to_tuple().ins_last( bt );
03900      S.ins( br );
03901 
03902      for (Iterator<Expression> iter = _arg_list; iter.valid(); ++iter) {
03903      bt->to_tuple().ins_last(
03904          new BinRep( iter.current().exchange_expr(vdl)));
03905      }
03906 
03907      return index;
03908  }
03909 
03910 
03911  void
03912  CommaExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
03913  {
03914      String          s;
03915      BinRep      second;     /// ...  The second argument of tuple pairs
03916 
03917      empty_overflow();
03918 
03919      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
03920                expr_iter.valid(); ++expr_iter) {
03921      String          field;
03922 
03923      expr_iter.current()[0].to_string(field);
03924      second = expr_iter.current()[1];
03925 
03926      if (field == "type")
03927          get_type(second, "Comma");
03928      else if (field == "args") {
03929          Iterator<BinRep>      iter = second.to_tuple();
03930 
03931          for (BinRep args; iter.valid(); ++iter) {
03932          args = iter.current();
03933 
03934          p_assert( args.is_integer(), "CommaExpr::convert: "
03935                "Non-Binary Op's arg field contains non-int" );
03936 
03937          Expression     *thug = tableEntry(args.to_integer());
03938          _arg_list.ins_last(thug);
03939          }
03940      }
03941      else if (field != "op" && field != "size")
03942          make_overflow(expr_iter, "CommaExpr");
03943      }
03944  }
03945 
03946  void
03947  CommaExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
03948  {
03949      print_prec_list(o, op(), _arg_list, ", ");
03950  }
03951 
03952  //-----------------------------------------------------------------------------
03953 /// ComplexExpr code:
03954 ///
03955 
03956 /// Note: The following data fields are aliased:
03957 /// real_part = left
03958 /// imaginary_part = right
03959 
03960  ComplexExpr::~ComplexExpr() 
03961  {
03962      /// ...  nothing to do
03963  }
03964 
03965  Expression     *
03966  ComplexExpr::clone() const
03967  {
03968      return new ComplexExpr(*this);
03969  }
03970 
03971  ComplexExpr &
03972  ComplexExpr::operator = (const ComplexExpr & e) 
03973  {
03974      BinaryExpr::operator = (e);
03975 
03976      return *this;
03977  }
03978 
03979  int
03980  ComplexExpr::structures_OK() const
03981  {
03982      cerr << "ComplexExpr::structures_OK() not implemented";
03983      return True;
03984  }
03985 
03986  int     
03987  ComplexExpr::exchange_expr( VDL & vdl )
03988  {
03989      int index = vdl.look_up_expr( *this );
03990 
03991      if (index >= 0)
03992      return index;
03993 
03994      index = Expression::exchange_expr( vdl );
03995 
03996      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
03997 
03998      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
03999 
04000      BinRep  *br = new BinRep( new List<BinRep> );
04001      br->to_tuple().ins_last(new BinRep( "op" ));
04002      br->to_tuple().ins_last(new BinRep( "COMPLEX" ));
04003      S.ins( br );
04004 
04005      br = new BinRep( new List<BinRep> );
04006      br->to_tuple().ins_last(new BinRep( "args" ));
04007      BinRep  *bt = new BinRep(new List<BinRep>);
04008      br->to_tuple().ins_last( bt );
04009      S.ins( br );
04010 
04011      bt->to_tuple().ins_last(
04012      new BinRep( this->left_guarded().exchange_expr(vdl)));
04013      bt->to_tuple().ins_last(
04014      new BinRep( this->right_guarded().exchange_expr(vdl)));
04015 
04016      return index;
04017  }
04018 
04019  void
04020  ComplexExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
04021  {
04022      String          s;
04023      BinRep      second;     /// ...  The second argument of tuple pairs
04024 
04025      empty_overflow();
04026 
04027      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04028                expr_iter.valid(); ++expr_iter) {
04029      String          field;
04030 
04031      expr_iter.current()[0].to_string(field);
04032      second = expr_iter.current()[1];
04033 
04034      if (field == "type") {
04035          second.to_string(s);
04036 
04037          p_assert( s == "COMPLEX",
04038                "ComplexExpr::convert: type field not COMPLEX." );
04039          _type = COMPLEX_TYPE;
04040      }
04041      else if (field == "args") {
04042          Iterator<BinRep>  iter = second.to_tuple();
04043          BinRep            theArg = iter.current();
04044 
04045          /// ...  first element of args tuple
04046 
04047          Expression     *e1;
04048 
04049          p_assert( theArg.is_integer(),
04050                "ComplexExpr::convert: arg field contains non-int." );
04051 
04052          e1 = tableEntry(theArg.to_integer());
04053 
04054          ++iter;
04055 
04056          theArg = iter.current();    /// ...  Second element of args tuple
04057 
04058          p_assert( theArg.is_integer(),
04059                "ComplexExpr::convert: arg field contains non-int." );
04060 
04061          Expression     *e2 = tableEntry(theArg.to_integer());
04062 
04063          _left(e1);
04064          _right(e2);
04065      }
04066      else if (field != "op" && field != "size")
04067          make_overflow(expr_iter, "ComplexExpr");
04068      }
04069  }
04070 
04071  void
04072  ComplexExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
04073  {    o << "(";
04074 
04075      if (_left_valid())
04076      o << _left_guarded();
04077      else
04078      o << "<UNDEFINED>";
04079 
04080      o << ", ";
04081 
04082      if (_right_valid())
04083      o << _right_guarded();
04084      else
04085      o << "<UNDEFINED>";
04086 
04087      o << ")";
04088  }
04089 
04090  //-----------------------------------------------------------------------------
04091 /// DoExpr code:
04092 ///
04093 
04094 /// Note: The following data fields are aliased:
04095 /// iolist = left
04096 /// iterator = right
04097 
04098  DoExpr::~DoExpr() 
04099  {
04100      /// ...  nothing to do
04101  }
04102 
04103  DoExpr &
04104  DoExpr::operator = (const DoExpr & e) 
04105  {
04106      BinaryExpr::operator = (e);
04107 
04108      return *this;
04109  }
04110 
04111  Expression     *
04112  DoExpr::clone() const
04113  {
04114      return new DoExpr(*this);
04115  }
04116 
04117  void 
04118  DoExpr::iolist(Expression * e)
04119  {
04120      p_assert(e->op() == COMMA_OP,
04121           "DoExpr:: iolist( ) not a CommaExpr");
04122      _left(e);
04123  }
04124 
04125  const Expression & 
04126  DoExpr::iolist() const 
04127  {
04128      return _left_guarded();
04129  }
04130 
04131  Expression & 
04132  DoExpr::iolist()
04133  {
04134      return _left_guarded();
04135  }
04136 
04137  void 
04138  DoExpr::iterator(Expression * e)
04139  {
04140      p_assert(e->op() == EQUAL_OP,
04141           "DoExpr:: iterator( ) not a EqualExpr");
04142      _right(e);
04143  }
04144 
04145  const Expression & 
04146  DoExpr::iterator() const 
04147  {
04148      return _right_guarded();
04149  }
04150 
04151  Expression & 
04152  DoExpr::iterator()
04153  {
04154      return _right_guarded();
04155  }
04156 
04157  int
04158  DoExpr::structures_OK() const
04159  {
04160      cerr << "DoExpr::structures_OK() not implemented";
04161      return True;
04162  }
04163 
04164  int     
04165  DoExpr::exchange_expr( VDL & vdl )
04166  {
04167      int index = vdl.look_up_expr( *this );
04168 
04169      if (index >= 0)
04170      return index;
04171 
04172      index = Expression::exchange_expr( vdl );
04173 
04174      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04175 
04176      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04177 
04178      BinRep  *br = new BinRep( new List<BinRep> );
04179      br->to_tuple().ins_last(new BinRep( "op" ));
04180      br->to_tuple().ins_last(new BinRep( "DO" ));
04181      S.ins( br );
04182 
04183      br = new BinRep( new List<BinRep> );
04184      br->to_tuple().ins_last(new BinRep( "args" ));
04185      BinRep  *bt = new BinRep(new List<BinRep>);
04186      br->to_tuple().ins_last( bt );
04187      S.ins( br );
04188 
04189      bt->to_tuple().ins_last(
04190      new BinRep( this->iolist().exchange_expr(vdl)));
04191      bt->to_tuple().ins_last(
04192      new BinRep( this->iterator().exchange_expr(vdl)));
04193 
04194      return index;
04195  }
04196 
04197 
04198  void
04199  DoExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
04200  {
04201      String          s;
04202      BinRep      second;     /// ...  The second argument of tuple pairs
04203 
04204      empty_overflow();
04205 
04206      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04207                expr_iter.valid(); ++expr_iter) {
04208      String          field;
04209 
04210      expr_iter.current()[0].to_string(field);
04211      second = expr_iter.current()[1];
04212 
04213      if (field == "type")
04214          get_type(second, "Do");
04215      else if (field == "args") {
04216          Iterator<BinRep>  iter = second.to_tuple();
04217          BinRep            theArg = iter.current();
04218 
04219          /// ...  first element of args tuple
04220 
04221          Expression     *e1;
04222 
04223          p_assert( theArg.is_integer(),
04224                "DoExpr::convert: arg field contains non-int." );
04225 
04226          e1 = tableEntry(theArg.to_integer());
04227 
04228          ++iter;
04229 
04230          theArg = iter.current();    /// ...  Second element of args tuple
04231 
04232          p_assert( theArg.is_integer(),
04233                "DoExpr::convert: arg field contains non-int." );
04234 
04235          Expression     *e2 = tableEntry(theArg.to_integer());
04236 
04237          _left(e1);
04238          _right(e2);
04239      }
04240      else if (field != "op" && field != "size")
04241          make_overflow(expr_iter, "DoExpr");
04242      }
04243  }
04244 
04245  void
04246  DoExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
04247  {
04248      o << "(";
04249      print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
04250      o << ", ";
04251      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
04252      o << ")";
04253  }
04254 
04255  //-----------------------------------------------------------------------------
04256 /// EqualExpr code:
04257 ///
04258 
04259 /// Note: The following data fields are aliased:
04260 /// index_id = left
04261 /// iteration_space = right
04262 
04263  EqualExpr::~EqualExpr() 
04264  {
04265      /// ...  nothing to do
04266  }
04267 
04268  Expression     *
04269  EqualExpr::clone() const
04270  {
04271      return new EqualExpr(*this);
04272  }
04273 
04274  EqualExpr &
04275  EqualExpr::operator = (const EqualExpr & e) 
04276  {
04277      BinaryExpr::operator = (e);
04278 
04279      return *this;
04280  }
04281 
04282  void 
04283  EqualExpr::index_id(Expression * e)
04284  {
04285      p_assert(e->op() == ID_OP,
04286           "EqualExpr::index_id( ) not an IDExpr");
04287      _left(e);
04288  }
04289 
04290  const Expression & 
04291  EqualExpr::index_id() const 
04292  {
04293      return _left_guarded();
04294  }
04295 
04296  Expression & 
04297  EqualExpr::index_id()
04298  {
04299      return _left_guarded();
04300  }
04301 
04302  void 
04303  EqualExpr::iteration_space(Expression * e)
04304  {
04305      p_assert(e->op() == COMMA_OP,
04306           "EqualExpr::iteration_space( ) not an CommaExpr");
04307      _right(e);
04308  }
04309 
04310  const Expression & 
04311  EqualExpr::iteration_space() const 
04312  {
04313      return _right_guarded();
04314  }
04315 
04316  Expression & 
04317  EqualExpr::iteration_space()
04318  {
04319      return _right_guarded();
04320  }
04321 
04322  int
04323  EqualExpr::structures_OK() const
04324  {
04325      cerr << "EqualExpr::structures_OK() not implemented";
04326      return True;
04327  }
04328 
04329  int     
04330  EqualExpr::exchange_expr( VDL & vdl )
04331  {
04332      int index = vdl.look_up_expr( *this );
04333 
04334      if (index >= 0)
04335      return index;
04336 
04337      index = Expression::exchange_expr( vdl );
04338 
04339      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04340 
04341      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04342 
04343      BinRep  *br = new BinRep( new List<BinRep> );
04344      br->to_tuple().ins_last(new BinRep( "op" ));
04345      br->to_tuple().ins_last(new BinRep( "=" ));
04346      S.ins( br );
04347 
04348      br = new BinRep( new List<BinRep> );
04349      br->to_tuple().ins_last(new BinRep( "args" ));
04350      BinRep  *bt = new BinRep(new List<BinRep>);
04351      br->to_tuple().ins_last( bt );
04352      S.ins( br );
04353 
04354      bt->to_tuple().ins_last(
04355      new BinRep( this->index_id().exchange_expr(vdl)));
04356      bt->to_tuple().ins_last(
04357      new BinRep( this->iteration_space().exchange_expr(vdl)));
04358 
04359      return index;
04360  }
04361 
04362 
04363  void
04364  EqualExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
04365  {
04366      String          s;
04367      BinRep      second;     /// ...  The second argument of tuple pairs
04368 
04369      empty_overflow();
04370 
04371      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04372                expr_iter.valid(); ++expr_iter) {
04373      String          field;
04374 
04375      expr_iter.current()[0].to_string(field);
04376      second = expr_iter.current()[1];
04377 
04378      if (field == "type")
04379          get_type(second, "Equal");
04380      else if (field == "args") {
04381          Iterator<BinRep>  iter = second.to_tuple();
04382          BinRep            theArg = iter.current();
04383 
04384          /// ...  first element of args tuple
04385 
04386          p_assert( theArg.is_integer(),
04387                "EqualExpr::convert: arg field contains non-int." );
04388 
04389          Expression     *e1 = tableEntry(theArg.to_integer());
04390 
04391          ++iter;
04392 
04393          theArg = iter.current();    /// ...  Second element of args tuple
04394 
04395          p_assert( theArg.is_integer(),
04396                "EqualExpr::convert: arg field contains non-int." );
04397 
04398          Expression     *e2 = tableEntry(theArg.to_integer());
04399 
04400          _left(e1);
04401          _right(e2);
04402      }
04403      else if (field != "op" && field != "size")
04404          make_overflow(expr_iter, "EqualExpr");
04405      }
04406  }
04407 
04408  void
04409  EqualExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
04410  {
04411      print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
04412      o << "=";
04413      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
04414  }
04415 
04416  //-----------------------------------------------------------------------------
04417 /// FormatExpr code:
04418 ///
04419 
04420 /// Note: The following data fields are aliased:
04421 /// format = data
04422 
04423  FormatExpr::~FormatExpr() 
04424  {
04425      /// ...  nothing to do
04426  }
04427 
04428  Expression     *
04429  FormatExpr::clone() const
04430  {
04431      return new FormatExpr(*this);
04432  }
04433 
04434  const Format &
04435  FormatExpr::format() const
04436  {
04437      return *_format_ptr;
04438  }
04439 
04440  Format &
04441  FormatExpr::format()
04442  {
04443      return *_format_ptr;
04444  }
04445 
04446  void
04447  FormatExpr::format(Format & format)
04448  {
04449      _format_ptr = &format;
04450  }
04451 
04452  int
04453  FormatExpr::structures_OK() const
04454  {
04455      cerr << "FormatExpr::structures_OK() not implemented";
04456      return True;
04457  }
04458 
04459  int     
04460  FormatExpr::exchange_expr( VDL & vdl )
04461  {
04462      int index = vdl.look_up_expr( *this );
04463 
04464      if (index >= 0)
04465      return index;
04466 
04467      index = Expression::exchange_expr( vdl );
04468 
04469      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04470 
04471      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04472 
04473      BinRep  *br = new BinRep( new List<BinRep> );
04474      br->to_tuple().ins_last(new BinRep( "op" ));
04475      br->to_tuple().ins_last(new BinRep( "FORMAT" ));
04476      S.ins( br );
04477 
04478      return index;
04479  }
04480 
04481 
04482  void
04483  FormatExpr::convert(BinRep & NOTUSED(exprSet), Symtab & NOTUSED(symtab))
04484  {
04485      /// ...  Currently, doesn't exist on setl side -- no need for conversion
04486  }
04487 
04488  void
04489  FormatExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
04490  {
04491    o << _format_ptr->value();
04492  }
04493 
04494  void 
04495  FormatExpr::relink_eptrs(ProgramUnit & p)
04496  {
04497      p_assert(_format_ptr, "FormatExpr has NULL pointer");
04498      int label = _format_ptr->value();
04499      _format_ptr = p.formats().find_ref(label);
04500      p_assert(_format_ptr, "FormatExpr has NULL pointer");
04501  }
04502 
04503  //-----------------------------------------------------------------------------
04504 /// FunctionCallExpr code:
04505 ///
04506 
04507 /// Note: The following data fields are aliased:
04508 /// function = left
04509 /// parameters = right
04510 
04511  FunctionCallExpr::~FunctionCallExpr() 
04512  {
04513      /// ...  nothing to do
04514  }
04515 
04516  Expression     *
04517  FunctionCallExpr::clone() const
04518  {
04519      return new FunctionCallExpr(*this);
04520  }
04521 
04522  FunctionCallExpr &
04523  FunctionCallExpr::operator = (const FunctionCallExpr & e) 
04524  {
04525      BinaryExpr::operator = (e);
04526 
04527      return *this;
04528  }
04529 
04530  void 
04531  FunctionCallExpr::function(Expression * e)
04532  {
04533      p_assert(e->op() == ID_OP,
04534           "FunctionCallExpr:: function( ) not an IDExpr");
04535      _left(e);
04536  }
04537 
04538  const Expression & 
04539  FunctionCallExpr::function() const 
04540  {
04541      return _left_guarded();
04542  }
04543 
04544  Expression & 
04545  FunctionCallExpr::function()
04546  {
04547      return _left_guarded();
04548  }
04549 
04550  void 
04551  FunctionCallExpr::parameters(Expression * e)
04552  {
04553      p_assert(e->op() == COMMA_OP || e->op() == OMEGA_OP,
04554           "FunctionCallExpr:: parameters( ) not an CommaExpr or OmegaExpr");
04555      _right(e);
04556  }
04557 
04558  const Expression & 
04559  FunctionCallExpr::parameters_guarded() const 
04560  {
04561      return _right_guarded();
04562  }
04563 
04564  Expression & 
04565  FunctionCallExpr::parameters_guarded() 
04566  {
04567      return _right_guarded();
04568  }
04569 
04570  Boolean
04571  FunctionCallExpr::parameters_valid() const 
04572  {
04573      return _right_valid();
04574  }
04575 
04576  int
04577  FunctionCallExpr::structures_OK() const
04578  {
04579      cerr << "FunctionCallExpr::structures_OK() not implemented";
04580      return True;
04581  }
04582 
04583  int     
04584  FunctionCallExpr::exchange_expr( VDL & vdl )
04585  {
04586      int index = vdl.look_up_expr( *this );
04587 
04588      if (index >= 0)
04589      return index;
04590 
04591      index = Expression::exchange_expr( vdl );
04592 
04593      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04594 
04595      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04596 
04597      BinRep  *br = new BinRep( new List<BinRep> );
04598      br->to_tuple().ins_last(new BinRep( "op" ));
04599      br->to_tuple().ins_last(new BinRep( "FUNCTION_CALL" ));
04600      S.ins( br );
04601 
04602      br = new BinRep( new List<BinRep> );
04603      br->to_tuple().ins_last(new BinRep( "args" ));
04604      BinRep  *bt = new BinRep(new List<BinRep>);
04605      br->to_tuple().ins_last( bt );
04606      S.ins( br );
04607 
04608      bt->to_tuple().ins_last(
04609      new BinRep( this->function().exchange_expr(vdl)));
04610      bt->to_tuple().ins_last(
04611      new BinRep( this->parameters_guarded().exchange_expr(vdl)));
04612 
04613      return index;
04614  }
04615 
04616 
04617  void
04618  FunctionCallExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
04619  {
04620      String          s;
04621      BinRep      second;     /// ...  The second argument of tuple pairs
04622 
04623      empty_overflow();
04624 
04625      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04626                expr_iter.valid(); ++expr_iter) {
04627      String          field;
04628 
04629      expr_iter.current()[0].to_string(field);
04630      second = expr_iter.current()[1];
04631 
04632      if (field == "type")
04633          get_type(second, "FunctionCall");
04634      else if (field == "args") {
04635          Iterator<BinRep> iter = second.to_tuple();
04636          BinRep           args = iter.current();
04637 
04638          p_assert( args.is_integer(), "FunctionCall::convert: "
04639                "Call's first arg field contains non-int." );
04640 
04641          Expression     *e1 = tableEntry(args.to_integer());
04642 
04643          _left(e1);
04644 
04645          ++iter;
04646 
04647          if (iter.valid()) {
04648          args = iter.current();
04649 
04650          p_assert( args.is_integer(), "FunctionCall::convert: "
04651                "Call's second arg field contains non-int." );
04652 
04653          e1 = tableEntry(args.to_integer());
04654 
04655          _right(e1);
04656          }
04657      }
04658      else if (field == "size") {
04659          p_assert( second.is_integer(), 
04660               "FunctionCallExpr::convert: 'size' field contains non-int");
04661          _type.set(second.to_integer());
04662      }
04663      else if (field != "op") {
04664          make_overflow(expr_iter, "FunctionCallExpr");
04665      }
04666      }
04667  }
04668 
04669  void
04670  FunctionCallExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
04671  {
04672      print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
04673      o << "(";
04674      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
04675      o << ")";
04676  }
04677 
04678  //-----------------------------------------------------------------------------
04679 /// HollerithConstExpr code:
04680 ///
04681 
04682  HollerithConstExpr::~HollerithConstExpr() 
04683  {
04684      /// ...  nothing to do
04685  }
04686 
04687  Expression     *
04688  HollerithConstExpr::clone() const
04689  {
04690      return new HollerithConstExpr(*this);
04691  }
04692 
04693  HollerithConstExpr &
04694  HollerithConstExpr::operator = (const HollerithConstExpr & e) 
04695  {
04696      StringExpr::operator = (e);
04697 
04698      return *this;
04699  }
04700 
04701  int
04702  HollerithConstExpr::structures_OK() const
04703  {
04704      cerr << "HollerithConstExpr::structures_OK() not implemented";
04705      return True;
04706  }
04707 
04708  int     
04709  HollerithConstExpr::exchange_expr( VDL & vdl )
04710  {
04711      int index = vdl.look_up_expr( *this );
04712 
04713      if (index >= 0)
04714      return index;
04715 
04716      index = Expression::exchange_expr( vdl );
04717 
04718      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04719 
04720      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04721 
04722      BinRep  *br = new BinRep( new List<BinRep> );
04723      br->to_tuple().ins_last(new BinRep( "op" ));
04724      br->to_tuple().ins_last(new BinRep( "HOLLERITH_CONSTANT" ));
04725      S.ins( br );
04726 
04727      return index;
04728  }
04729 
04730 
04731  void
04732  HollerithConstExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
04733  {
04734      String          s;
04735      BinRep      second;     /// ...  The second argument of tuple pairs
04736 
04737      empty_overflow();
04738 
04739      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04740                expr_iter.valid(); ++expr_iter) {
04741      String          field;
04742 
04743      expr_iter.current()[0].to_string(field);
04744      second = expr_iter.current()[1];
04745 
04746      if (field == "type") {
04747          p_assert( second.is_string(), "HollerithConstExpr::convert: "
04748                "type field doesn't contain string." );
04749 
04750          second.to_string(s);
04751 
04752          p_assert( s == "CHARACTER", "HollerithConstExpr::convert: "
04753                "type field not CHARACTER" );
04754          _type = (CHARACTER_TYPE);
04755      }
04756      else if (field == "data") {
04757          p_assert( second.is_string(), "HollerithConst::convert: "
04758                "'data' field does not contain an string." );
04759          second.to_string(_data);
04760      }
04761      else if (field == "size") {
04762          p_assert( second.is_integer(), "HollerithConstExpr::convert: "
04763                "'size' field contains non-int." );
04764          _type.set(second.to_integer());
04765      }
04766      else if (field != "op")
04767          make_overflow(expr_iter, "HollerithConstExpr");
04768      }
04769  }
04770 
04771  //-----------------------------------------------------------------------------
04772 /// IDExpr code:
04773 ///
04774 
04775  IDExpr::~IDExpr() 
04776  {
04777      if (_substituted)
04778      delete _substituted;
04779      if (_arcs)
04780     delete _arcs;
04781  }
04782 
04783  Expression     *
04784  IDExpr::clone() const
04785  {
04786      return new IDExpr(*this);
04787  }
04788 
04789  IDExpr &
04790  IDExpr::operator = (const IDExpr & e) 
04791  {
04792      if (this != &e) {
04793      if (_substituted)
04794          delete _substituted;
04795 
04796      _symbol = CASTAWAY(Symbol *) &e.symbol();
04797 
04798      if (e.substituted_valid())
04799          _substituted = e.substituted_guarded().clone();
04800      else
04801          _substituted = 0;
04802 
04803      _arcs = 0;
04804      }
04805 
04806      return *this;
04807  }
04808 
04809  const Expression &
04810  IDExpr::substituted_guarded() const
04811  {
04812      p_assert(_substituted, 
04813           "Guarded method called when field (_substituted) was NULL");
04814 
04815      return *_substituted;
04816  }
04817 
04818  Expression &
04819  IDExpr::substituted_guarded()
04820  {
04821      p_assert(_substituted, 
04822           "Guarded method called when field (_substituted) was NULL");
04823 
04824      return *_substituted;
04825  }
04826 
04827  Boolean
04828  IDExpr::substituted_valid() const
04829  {
04830      if (_substituted)
04831      return True;
04832      else
04833      return False;
04834  }
04835 
04836  void
04837  IDExpr::substituted(Expression * e)
04838  {
04839      if (_substituted)
04840      delete _substituted;
04841 
04842      _substituted = e;
04843  }
04844 
04845  Expression *
04846  IDExpr::grab_substituted()
04847  {
04848      Expression *temp = _substituted;
04849      _substituted = 0;
04850      return temp;
04851  }
04852 
04853  const Symbol &
04854  IDExpr::symbol() const
04855  {
04856      return *_symbol;
04857  }
04858 
04859  Symbol &
04860  IDExpr::symbol()
04861  {
04862      return *_symbol;
04863  }
04864 
04865  void
04866  IDExpr::symbol(const Symbol & s)
04867  {
04868      _symbol = CASTAWAY(Symbol *)&s;
04869  }
04870 
04871  int
04872  IDExpr::structures_OK() const
04873  {
04874      cerr << "ID::structures_OK() not implemented";
04875      return True;
04876  }
04877 
04878  int     
04879  IDExpr::exchange_expr( VDL & vdl )
04880  {
04881      int index = vdl.look_up_expr( *this );
04882 
04883      if (index >= 0)
04884      return index;
04885 
04886      index = Expression::exchange_expr( vdl );
04887 
04888      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
04889 
04890      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
04891 
04892      BinRep  *br = new BinRep( new List<BinRep> );
04893      br->to_tuple().ins_last(new BinRep( "op" ));
04894      br->to_tuple().ins_last(new BinRep( "ID" ));
04895      S.ins( br );
04896 
04897      br = new BinRep( new List<BinRep> );
04898      br->to_tuple().ins_last(new BinRep( "name" ));
04899      br->to_tuple().ins_last(new BinRep( this->symbol().name_ref() ));
04900      S.ins( br );
04901 
04902      return index;
04903  }
04904 
04905 
04906  void
04907  IDExpr::convert(BinRep & exprSet, Symtab & symtab)
04908  {
04909      String          s;
04910      BinRep      second;     /// ...  The second argument of tuple pairs
04911 
04912      empty_overflow();
04913 
04914      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
04915                expr_iter.valid(); ++expr_iter) {
04916      String          field;
04917 
04918      expr_iter.current()[0].to_string(field);
04919      second = expr_iter.current()[1];
04920 
04921      if (field == "type")
04922          get_type(second, "ID");
04923      else if (field == "size") {
04924          p_assert( second.is_integer(), "IDExpr::convert: "
04925                "'size' field contains non-int" );
04926          _type.set(second.to_integer());
04927      }
04928      else if (field == "name") {
04929          p_assert( second.is_string(), "IDExpr::convert: "
04930                " 'name' field contains non-string" );
04931 
04932          String          idname;
04933 
04934          second.to_string(idname);
04935          _symbol = symtab.find_ref(idname);
04936 
04937          if (! _symbol) {
04938          cerr << "IDExpr::convert: "
04939               << "Symbol table does not contain entry for "
04940               << idname << endl;
04941          p_abort("(See above error message)");
04942          }
04943      }
04944      else if (field == "substituted") {
04945          p_assert( second.is_integer(),
04946                "fillExpr:  'substituted' field contains non-int" );
04947 
04948          _substituted = tableEntry(second.to_integer());
04949      }
04950      else if (field != "op" && field != "size")
04951          make_overflow(expr_iter, "IDExpr");
04952      }
04953  }
04954 
04955  void
04956  IDExpr::print_debug(ostream & o, Boolean debug) const
04957  {
04958 
04959      if (! _symbol)
04960      o << "(NO SYMBOL)";
04961      else {
04962      o << convert_case( _symbol->name_ref() );
04963      }
04964      if (debug) {
04965      if (_substituted)
04966          o << "[" << *_substituted << "]";
04967      }
04968  }
04969 
04970  void 
04971  IDExpr::relink_eptrs(ProgramUnit & p)
04972  {
04973      p_assert(_symbol, "IDExpr has NULL pointer");
04974      _symbol = p.symtab().find_ref(_symbol->name_ref());
04975      p_assert(_symbol, "IDExpr has NULL pointer");
04976  }
04977 
04978  //-----------------------------------------------------------------------------
04979 /// IOStarExpr code:
04980 ///
04981 
04982  IOStarExpr::~IOStarExpr() 
04983  {
04984      /// ...  nothing to do
04985  }
04986 
04987  Expression     *
04988  IOStarExpr::clone() const
04989  {
04990      return new IOStarExpr(*this);
04991  }
04992 
04993  IOStarExpr &
04994  IOStarExpr::operator = (const IOStarExpr & NOTUSED(e))
04995  {
04996      return *this;
04997  }
04998 
04999  int
05000  IOStarExpr::structures_OK() const
05001  {
05002      cerr << "IOStar::structures_OK() not implemented";
05003      return True;
05004  }
05005 
05006  int     
05007  IOStarExpr::exchange_expr( VDL & vdl )
05008  {
05009      int index = vdl.look_up_expr( *this );
05010 
05011      if (index >= 0)
05012      return index;
05013 
05014      index = Expression::exchange_expr( vdl );
05015 
05016      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05017 
05018      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05019 
05020      BinRep  *br = new BinRep( new List<BinRep> );
05021      br->to_tuple().ins_last(new BinRep( "op" ));
05022      br->to_tuple().ins_last(new BinRep( "IO*" ));
05023      S.ins( br );
05024 
05025      return index;
05026  }
05027 
05028 
05029  void
05030  IOStarExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05031  {
05032      String          s;
05033      BinRep      second;     /// ...  The second argument of tuple pairs
05034 
05035      empty_overflow();
05036 
05037      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05038                expr_iter.valid(); ++expr_iter) {
05039      String          field;
05040 
05041      expr_iter.current()[0].to_string(field);
05042      second = expr_iter.current()[1];
05043 
05044      if (field == "type")
05045          get_type(second, "IOStar");
05046      else if (field != "op" && field != "size")
05047          make_overflow(expr_iter, "IOStarExpr");
05048      }
05049  }
05050 
05051  void
05052  IOStarExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05053  {
05054      o << "*";
05055  }
05056 
05057  //-----------------------------------------------------------------------------
05058 /// InfinityExpr code:
05059 ///
05060 
05061  InfinityExpr::~InfinityExpr()
05062  {
05063      /// ...  Nothing to do
05064  }
05065 
05066  Expression *
05067  InfinityExpr::clone() const
05068  {
05069      return new InfinityExpr(*this);
05070  }
05071 
05072  InfinityExpr &
05073  InfinityExpr::operator = (const InfinityExpr & other)
05074  {
05075      _sign = other._sign;
05076      return *this;
05077  }
05078 
05079  void
05080  InfinityExpr::sign(int s)
05081  {
05082      _sign = (s >= 0) ? 1: -1;
05083  }
05084 
05085  int
05086  InfinityExpr::sign() const
05087  {
05088      return _sign;
05089  }
05090 
05091  int
05092  InfinityExpr::structures_OK() const
05093  {
05094      if (_sign == 0) {
05095      cerr << "InfinityExpr::structures_OK(): Expression has a zero sign.\n";
05096      return False;
05097      }
05098      else if (type().data_type() != INTEGER_TYPE) {
05099      cerr << "InfinityExpr::structures_OK(): "
05100           << "Expression has a non-integer type.\n";
05101      return False;
05102      }
05103 
05104      return True;
05105  }
05106 
05107  int     
05108  InfinityExpr::exchange_expr( VDL & vdl )
05109  {
05110      int index = vdl.look_up_expr( *this );
05111 
05112      if (index >= 0)
05113      return index;
05114 
05115      index = Expression::exchange_expr( vdl );
05116 
05117      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05118 
05119      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05120 
05121      BinRep  *br = new BinRep( new List<BinRep> );
05122      br->to_tuple().ins_last(new BinRep( "op" ));
05123      br->to_tuple().ins_last(new BinRep( "INFINITY" ));
05124      S.ins( br );
05125 
05126      return index;
05127  }
05128 
05129 
05130  void
05131  InfinityExpr::convert(BinRep & NOTUSED(exprSet), 
05132                Symtab & NOTUSED(symtab))
05133  {
05134      p_abort( "Cannot read a InfinityExpr object from a binstring.");
05135  }
05136 
05137  void
05138  InfinityExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05139  {
05140      if (_sign >= 0)
05141      o << "Inf";
05142      else
05143      o << "-Inf";
05144  }
05145 
05146  //-----------------------------------------------------------------------------
05147 /// IntConstExpr code:
05148 ///
05149 
05150  IntConstExpr::~IntConstExpr() 
05151  {
05152      /// ...  nothing to do
05153  }
05154 
05155  int
05156  IntConstExpr::value() const
05157  {
05158      return _value;
05159  }
05160 
05161  void
05162  IntConstExpr::value(int v)
05163  {
05164      _value = v;
05165  }
05166 
05167  Expression     *
05168  IntConstExpr::clone() const
05169  {
05170      return new IntConstExpr(*this);
05171  }
05172 
05173  IntConstExpr &
05174  IntConstExpr::operator = (const IntConstExpr & e) 
05175  {
05176      if (this != &e)
05177      _value = e.value();
05178 
05179      return *this;
05180  }
05181 
05182  int
05183  IntConstExpr::structures_OK() const
05184  {
05185      cerr << "IntConstExpr::structures_OK() not implemented";
05186      return True;
05187  }
05188 
05189  int     
05190  IntConstExpr::exchange_expr( VDL & vdl )
05191  {
05192      int index = vdl.look_up_expr( *this );
05193 
05194      if (index >= 0)
05195      return index;
05196 
05197      index = Expression::exchange_expr( vdl );
05198 
05199      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05200 
05201      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05202 
05203      BinRep  *br = new BinRep( new List<BinRep> );
05204      br->to_tuple().ins_last(new BinRep( "op" ));
05205      br->to_tuple().ins_last(new BinRep( "INTEGER_CONSTANT" ));
05206      S.ins( br );
05207 
05208      br = new BinRep( new List<BinRep> );
05209      br->to_tuple().ins_last(new BinRep( "data" ));
05210      br->to_tuple().ins_last(new BinRep( this->value() ));
05211      S.ins( br );
05212 
05213      return index;
05214  }
05215 
05216 
05217  void
05218  IntConstExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05219  {
05220      String          s;
05221      BinRep      second;     /// ...  The second argument of tuple pairs
05222 
05223      empty_overflow();
05224 
05225      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05226                expr_iter.valid(); ++expr_iter) {
05227      String          field;
05228 
05229      expr_iter.current()[0].to_string(field);
05230      second = expr_iter.current()[1];
05231 
05232      if (field == "type") {
05233          p_assert( second.is_string(), "IntConstExpr::convert: "
05234                "type field doesn't contain string" );
05235 
05236          second.to_string(s);
05237 
05238          p_assert( (s == "INTEGER"), "IntConstExpr not of INTEGER type" );
05239          _type = INTEGER_TYPE;
05240      }
05241      else if (field == "data") {
05242          if (!second.is_integer()) {
05243          cerr << "IntConstExpr's 'data' field contains non-int in : "
05244               << exprSet << endl;
05245          p_abort("(See above error message)");
05246          }
05247          else
05248          _value = second.to_integer();
05249      }
05250      else if (field != "op" && field != "size")
05251          make_overflow(expr_iter, "IntConstExpr");
05252      }
05253  }
05254 
05255  void
05256  IntConstExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05257  {
05258      o << _value;
05259  }
05260 
05261  //-----------------------------------------------------------------------------
05262 /// IntrinsicCallExpr code:
05263 ///
05264 
05265 /// Note: The following data fields are aliased:
05266 /// intrinsic = left
05267 /// parameters = right
05268 
05269  IntrinsicCallExpr::~IntrinsicCallExpr() 
05270  {
05271      /// ...  nothing to do
05272  }
05273 
05274  Expression     *
05275  IntrinsicCallExpr::clone() const
05276  {
05277      return new IntrinsicCallExpr(*this);
05278  }
05279 
05280  IntrinsicCallExpr & IntrinsicCallExpr::operator = (const IntrinsicCallExpr & e) {
05281      BinaryExpr::operator = (e);
05282      return *this;
05283  }
05284 
05285  void 
05286  IntrinsicCallExpr::intrinsic(Expression * e)
05287  {
05288      p_assert(e->op() == ID_OP,
05289           "IntrinsicCallExpr::Intrinsic( ) not an IDExpr");
05290      _left(e);
05291  }
05292 
05293  const Expression & 
05294  IntrinsicCallExpr::intrinsic() const 
05295  {
05296      return _left_guarded();
05297  }
05298 
05299  Expression & 
05300  IntrinsicCallExpr::intrinsic()
05301  {
05302      return _left_guarded();
05303  }
05304 
05305  void 
05306  IntrinsicCallExpr::parameters(Expression * e)
05307  {
05308      p_assert(e->op() == COMMA_OP,
05309           "IntrinsicCallExpr::Parameters( ) not a CommaExpr");
05310      _right(e);
05311  }
05312 
05313  const Expression & 
05314  IntrinsicCallExpr::parameters_guarded() const 
05315  {
05316      return _right_guarded();
05317  }
05318 
05319  Expression & 
05320  IntrinsicCallExpr::parameters_guarded()
05321  {
05322      return _right_guarded();
05323  }
05324 
05325  Boolean
05326  IntrinsicCallExpr::parameters_valid() const 
05327  {
05328      return _right_valid();
05329  }
05330 
05331  int
05332  IntrinsicCallExpr::structures_OK() const
05333  {
05334      cerr << "IntrinsicCallExpr::structures_OK() not implemented";
05335      return True;
05336  }
05337 
05338  int     
05339  IntrinsicCallExpr::exchange_expr( VDL & vdl )
05340  {
05341      int index = vdl.look_up_expr( *this );
05342 
05343      if (index >= 0)
05344      return index;
05345 
05346      index = Expression::exchange_expr( vdl );
05347 
05348      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05349 
05350      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05351 
05352      BinRep  *br = new BinRep( new List<BinRep> );
05353      br->to_tuple().ins_last(new BinRep( "op" ));
05354      br->to_tuple().ins_last(new BinRep( "INTRINSIC_CALL" ));
05355      S.ins( br );
05356 
05357      br = new BinRep( new List<BinRep> );
05358      br->to_tuple().ins_last(new BinRep( "args" ));
05359      BinRep  *bt = new BinRep(new List<BinRep>);
05360      br->to_tuple().ins_last( bt );
05361      S.ins( br );
05362 
05363      bt->to_tuple().ins_last(
05364      new BinRep( this->intrinsic().exchange_expr(vdl)));
05365      bt->to_tuple().ins_last(
05366      new BinRep( this->parameters_guarded().exchange_expr(vdl)));
05367 
05368      return index;
05369  }
05370 
05371 
05372  void
05373  IntrinsicCallExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05374  {
05375      String          s;
05376      BinRep      second;     /// ...  The second argument of tuple pairs
05377 
05378      empty_overflow();
05379 
05380      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05381                expr_iter.valid(); ++expr_iter) {
05382      String          field;
05383 
05384      expr_iter.current()[0].to_string(field);
05385      second = expr_iter.current()[1];
05386 
05387      if (field == "type")
05388          get_type(second, "IntrinsicCall");
05389      else if (field == "args") {
05390          Iterator<BinRep>  iter = second.to_tuple();
05391          BinRep          & args = iter.current();
05392 
05393          p_assert( args.is_integer(), "IntrinsicCall::convert: "
05394                "Call's first arg field contains non-int" );
05395 
05396          Expression     *e1 = tableEntry(args.to_integer());
05397 
05398          _left(e1);
05399 
05400          ++iter;
05401 
05402          if (iter.valid()) {
05403          args = iter.current();
05404 
05405          p_assert( (args.is_integer()), "IntrinsicCall::convert: "
05406                "Call's second arg field contains non-int" );
05407 
05408          e1 = tableEntry(args.to_integer());
05409 
05410          _right(e1);
05411          }
05412      }
05413      else if (field != "op" && field != "size")
05414          make_overflow(expr_iter, "IntrinsicCall");
05415      }
05416  }
05417 
05418  void
05419  IntrinsicCallExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05420  {
05421      /// ...  Apply translate_special_name to the intrinsic function name, since
05422      /// ...  it may have a machine-specific form
05423 
05424      if (_left_valid()) {
05425      o << translate_special_name(this->intrinsic().symbol().name_ref());
05426      } else {
05427      o << "<UNDEF>";
05428      }
05429 
05430      o << "(";
05431      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
05432      o << ")";
05433  }
05434 
05435  //-----------------------------------------------------------------------------
05436 /// LabelExpr code:
05437 ///
05438 /// Note: The following data fields are aliased:
05439 /// label = data
05440 
05441  LabelExpr::~LabelExpr() 
05442  {
05443      /// ...  nothing to do
05444  }
05445 
05446  LabelExpr &
05447  LabelExpr::operator = (const LabelExpr & e) 
05448  {
05449      _stmt = e._stmt;
05450      return *this;
05451  }
05452 
05453  Expression     *
05454  LabelExpr::clone() const
05455  {
05456      return new LabelExpr(*this);
05457  }
05458 
05459  const Statement &
05460  LabelExpr::stmt() const
05461  {
05462      return *_stmt;
05463  }
05464 
05465  Statement &
05466  LabelExpr::stmt()
05467  {
05468      return *_stmt;
05469  }
05470 
05471  void
05472  LabelExpr::stmt(Statement & stmt)
05473  {
05474    p_assert(stmt.stmt_class()==LABEL_STMT,
05475         "LabelExpr::stmt: attempt to point at non-label");
05476    _stmt = &stmt;
05477  }
05478 
05479  void
05480  LabelExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05481  {
05482      if (_stmt) {
05483      o << _stmt->value();
05484      }
05485      else {
05486      o << "<UNDEFINED STMT>";
05487      }
05488  }
05489 
05490  int
05491  LabelExpr::structures_OK() const
05492  {
05493      if (!_stmt) {
05494      cerr << "LabelExpr::structures_OK(): Found NULL _stmt field\n";
05495      cerr << "In LabelExpr:\n" << flush << *this;
05496      return False;
05497      }
05498 
05499      if (!_stmt->structures_OK()) {
05500      cerr << "In context of LabelExpr:\n" << flush << *this;
05501      return False;
05502      }
05503 
05504      return True;
05505  }
05506 
05507  void 
05508  LabelExpr::relink_eptrs(ProgramUnit & p)
05509  {
05510      p_assert(_stmt, "LabelExpr has NULL pointer");
05511      _stmt = p.stmts().find_ref(_stmt->tag());
05512      p_assert(_stmt, "LabelExpr has NULL pointer");
05513  }
05514 
05515  int     
05516  LabelExpr::exchange_expr( VDL & vdl )
05517  {
05518      int index = vdl.look_up_expr( *this );
05519 
05520      if (index >= 0)
05521      return index;
05522 
05523      index = Expression::exchange_expr( vdl );
05524 
05525      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05526 
05527      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05528 
05529      BinRep  *br = new BinRep( new List<BinRep> );
05530      br->to_tuple().ins_last(new BinRep( "op" ));
05531      br->to_tuple().ins_last(new BinRep( "LABEL" ));
05532      S.ins( br );
05533 
05534      return index;
05535  }
05536 
05537 
05538  void
05539  LabelExpr::convert(BinRep & NOTUSED(exprSet), Symtab & NOTUSED(symtab))
05540  {
05541      p_abort( "Internal Error: The conversion of a binstring to an "
05542           "Expression came across an old \"label\" op, which was "
05543           "believed to no longer be attainable outside of the "
05544           "scanner.  Please report this bug to the development "
05545           "group.  To the development group:  See the comments "
05546           "in the LabelExpr::convert() routine.");
05547 
05548      /// ...  NOTE:  See also the p_assert() in ExprTable.cc's get_expr_obj()
05549 
05550      /// ...  The old LabelExpr class to which the "label" op used to
05551      /// ...  be converted can still be used here.  However, the old
05552      /// ...  LabelExpr contained a string label,
05553      /// ...  the new one expects a statement label, so the convert
05554      /// ...  routine must simply be changed to convert the statement label
05555      /// ...  string into a statement pointer.
05556 
05557  #if 0
05558      String          s; 
05559      BinRep      second; /// ...  The second argument of tuple pairs
05560 
05561      empty_overflow();
05562 
05563      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05564                expr_iter.valid(); ++expr_iter) {
05565     String          field;
05566 
05567      expr_iter.current()[0].to_string(field); 
05568      second = expr_iter.current()[1];
05569 
05570      if (field == "type") 
05571          get_type(second, "Label"); 
05572      else if (field == "label") { 
05573          p_assert( second.is_string(), "LabelExpr::convert: "
05574                "'label' field does not contain label" ); 
05575          second.to_string(_data); 
05576      } 
05577      else if (field != "op")
05578          make_overflow(expr_iter, "LabelExpr"); 
05579      } 
05580  #endif
05581  }
05582 
05583  //-----------------------------------------------------------------------------
05584 /// LambdaCallExpr code:
05585 ///
05586 /// Note: The following data fields are aliased:
05587 /// expr = left
05588 /// parameters = right;
05589 
05590  LambdaCallExpr::~LambdaCallExpr() 
05591  {
05592      /// ...  nothing to do
05593  }
05594 
05595  Expression     *
05596  LambdaCallExpr::clone() const
05597  {
05598      return new LambdaCallExpr(*this);
05599  }
05600 
05601  LambdaCallExpr & 
05602  LambdaCallExpr::operator = (const LambdaCallExpr & e) 
05603  {
05604      BinaryExpr::operator = (e);
05605 
05606      return *this;
05607  }
05608 
05609  void
05610  LambdaCallExpr::lambda_expr(Expression * e) 
05611  {
05612      _left(e);
05613  }
05614 
05615  const Expression & 
05616  LambdaCallExpr::lambda_expr() const 
05617  {
05618      return _left_guarded();
05619  }
05620 
05621  Expression & 
05622  LambdaCallExpr::lambda_expr()
05623  {
05624      return _left_guarded();
05625  }
05626 
05627  void 
05628  LambdaCallExpr::parameters(Expression * e)
05629  {
05630      p_assert(e->op() == COMMA_OP,
05631           "LambdaCallExpr::parameters( ) not a CommaExpr");
05632      _right(e);
05633  }
05634 
05635  const Expression & 
05636  LambdaCallExpr::parameters_guarded() const 
05637  {
05638      return _right_guarded();
05639  }
05640 
05641  Expression & 
05642  LambdaCallExpr::parameters_guarded() 
05643  {
05644      return _right_guarded();
05645  }
05646 
05647  Boolean
05648  LambdaCallExpr::parameters_valid() const 
05649  {
05650      return _right_valid();
05651  }
05652 
05653  int
05654  LambdaCallExpr::structures_OK() const
05655  {
05656      cerr << "LambdaCallExpr::structures_OK() not implemented";
05657      return True;
05658  }
05659 
05660  int     
05661  LambdaCallExpr::exchange_expr( VDL & vdl )
05662  {
05663      int index = vdl.look_up_expr( *this );
05664 
05665      if (index >= 0)
05666      return index;
05667 
05668      index = Expression::exchange_expr( vdl );
05669 
05670      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05671 
05672      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05673 
05674      BinRep  *br = new BinRep( new List<BinRep> );
05675      br->to_tuple().ins_last(new BinRep( "op" ));
05676      br->to_tuple().ins_last(new BinRep( "LAMBDA_CALL" ));
05677      S.ins( br );
05678 
05679      br = new BinRep( new List<BinRep> );
05680      br->to_tuple().ins_last(new BinRep( "args" ));
05681      BinRep  *bt = new BinRep(new List<BinRep>);
05682      br->to_tuple().ins_last( bt );
05683      S.ins( br );
05684 
05685      bt->to_tuple().ins_last(
05686      new BinRep( this->lambda_expr().exchange_expr(vdl)));
05687      bt->to_tuple().ins_last(
05688      new BinRep( this->parameters_guarded().exchange_expr(vdl)));
05689 
05690      return index;
05691  }
05692 
05693 
05694  void
05695  LambdaCallExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05696  {
05697      String          s;
05698      BinRep      second;     /// ...  The second argument of tuple pairs
05699 
05700      empty_overflow();
05701 
05702      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05703                expr_iter.valid(); ++expr_iter) {
05704      String          field;
05705 
05706      expr_iter.current()[0].to_string(field);
05707      second = expr_iter.current()[1];
05708 
05709      if (field == "type")
05710          get_type(second, "LambdaCall");
05711      else if (field == "args") {
05712          Iterator<BinRep>   iter = second.to_tuple();
05713          BinRep           & args = iter.current();
05714 
05715          p_assert( args.is_integer(), "LambdaCall::convert: "
05716                "Call's first arg field contains non-int" );
05717 
05718          Expression     *e1 = tableEntry(args.to_integer());
05719 
05720          _left(e1);
05721 
05722          ++iter;
05723 
05724          if (iter.valid()) {
05725          args = iter.current();
05726 
05727          p_assert( args.is_integer(), "LambdaCall::convert: "
05728                "Call's second arg field contains non-int" );
05729 
05730          e1 = tableEntry(args.to_integer());
05731 
05732          _right(e1);
05733          }
05734      }
05735      else if (field != "op" && field != "size")
05736          make_overflow(expr_iter, "LambdaCall");
05737      }
05738  }
05739 
05740  void
05741  LambdaCallExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
05742  {
05743      print_prec(op(), (_left_valid() ? &_left_guarded() : 0), o);
05744      o << "(";
05745      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
05746      o << ")";
05747  }
05748 
05749  //-----------------------------------------------------------------------------
05750 /// LogicalConstExpr code:
05751 ///
05752 
05753  LogicalConstExpr::~LogicalConstExpr() 
05754  {
05755      /// ...  nothing to do
05756  }
05757 
05758  LogicalConstExpr & 
05759  LogicalConstExpr::operator = (const LogicalConstExpr & e) 
05760  {
05761      StringExpr::operator = (e);
05762 
05763      return *this;
05764  }
05765 
05766  Expression     *
05767  LogicalConstExpr::clone() const
05768  {
05769      return new LogicalConstExpr(*this);
05770  }
05771 
05772  int
05773  LogicalConstExpr::structures_OK() const
05774  {
05775      cerr << "LogicalConstExpr::structures_OK() not implemented";
05776      return True;
05777  }
05778 
05779  int     
05780  LogicalConstExpr::exchange_expr( VDL & vdl )
05781  {
05782      int index = vdl.look_up_expr( *this );
05783 
05784      if (index >= 0)
05785      return index;
05786 
05787      index = Expression::exchange_expr( vdl );
05788 
05789      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05790 
05791      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05792 
05793      BinRep  *br = new BinRep( new List<BinRep> );
05794      br->to_tuple().ins_last(new BinRep( "op" ));
05795      br->to_tuple().ins_last(new BinRep( "LOGICAL_CONSTANT" ));
05796      S.ins( br );
05797 
05798      br = new BinRep( new List<BinRep> );
05799      br->to_tuple().ins_last(new BinRep( "data" ));
05800      br->to_tuple().ins_last(new BinRep( this->data_ref() ));
05801      S.ins( br );
05802 
05803      return index;
05804  }
05805 
05806 
05807  void
05808  LogicalConstExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05809  {
05810      String          s;
05811      BinRep      second;     /// ...  The second argument of tuple pairs
05812 
05813      empty_overflow();
05814 
05815      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05816                expr_iter.valid(); ++expr_iter) {
05817      String          field;
05818 
05819      expr_iter.current()[0].to_string(field);
05820      second = expr_iter.current()[1];
05821 
05822      if (field == "type") {
05823          p_assert( second.is_string(), "LogicalConstExpr::convert: "
05824                "type field doesn't contain string" );
05825          second.to_string(s);
05826 
05827          p_assert( (s == "LOGICAL"),
05828                "LogicalConstExpr::convert: type field not LOGICAL" );
05829          _type = (LOGICAL_TYPE);
05830      }
05831      else if (field == "data") {
05832          p_assert( second.is_string(), "LogicalConst::convert: "
05833                "'data' field does not contain an string." );
05834          second.to_string(_data);
05835      }
05836      else if (field != "op" && field != "size")
05837          make_overflow(expr_iter, "LogicalConstExpr");
05838      }
05839  }
05840 
05841  //-----------------------------------------------------------------------------
05842 /// KeyExpr code:
05843 ///
05844 
05845  KeyExpr::~KeyExpr() 
05846  {
05847      /// ...  nothing to do
05848  }
05849 
05850  KeyExpr & 
05851  KeyExpr::operator = (const KeyExpr & e) 
05852  {
05853      StringExpr::operator = (e);
05854 
05855      return *this;
05856  }
05857 
05858  Expression     *
05859  KeyExpr::clone() const
05860  {
05861      return new KeyExpr(*this);
05862  }
05863 
05864  int
05865  KeyExpr::structures_OK() const
05866  {
05867      return True;
05868  }
05869 
05870  int     
05871  KeyExpr::exchange_expr( VDL & vdl )
05872  {
05873      int index = vdl.look_up_expr( *this );
05874 
05875      if (index >= 0)
05876      return index;
05877 
05878      index = Expression::exchange_expr( vdl );
05879 
05880      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05881 
05882      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
05883 
05884      BinRep  *br = new BinRep( new List<BinRep> );
05885      br->to_tuple().ins_last(new BinRep( "op" ));
05886      br->to_tuple().ins_last(new BinRep( "KEY" ));
05887      S.ins( br );
05888 
05889      br = new BinRep( new List<BinRep> );
05890      br->to_tuple().ins_last(new BinRep( "data" ));
05891      br->to_tuple().ins_last(new BinRep( this->data_ref() ));
05892      S.ins( br );
05893 
05894      return index;
05895  }
05896 
05897 
05898  void
05899  KeyExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
05900  {
05901      String          s;
05902      BinRep      second;     /// ...  The second argument of tuple pairs
05903 
05904      empty_overflow();
05905 
05906      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
05907                expr_iter.valid(); ++expr_iter) {
05908      String          field;
05909 
05910      expr_iter.current()[0].to_string(field);
05911      second = expr_iter.current()[1];
05912 
05913      if (field == "data") {
05914          p_assert( second.is_string(), "KeyExpr::convert: "
05915                "'data' field does not contain an string." );
05916          second.to_string(_data);
05917      }
05918      else if (field != "op" && field != "size" && field != "type")
05919          make_overflow(expr_iter, "KeyExpr");
05920      }
05921  }
05922 
05923  //-----------------------------------------------------------------------------
05924 /// NonBinaryExpr code:
05925 ///
05926 
05927  NonBinaryExpr::~NonBinaryExpr()
05928  {
05929      /// ...  nothing to do
05930  }
05931 
05932  Expression     *
05933  NonBinaryExpr::clone() const
05934  {
05935      return new NonBinaryExpr(*this);
05936  }
05937 
05938  NonBinaryExpr::NonBinaryExpr(OP_TYPE o, const Type & e, List<Expression> *list)
05939      : Expression(o, e)
05940  {
05941      for (Iterator<Expression>iter = *list; iter.valid(); ++iter) 
05942      _arg_list.ins_last(list->grab(iter.current()));
05943 
05944      delete list;
05945  }
05946 
05947  NonBinaryExpr &
05948  NonBinaryExpr::operator = (const NonBinaryExpr & e) 
05949  {
05950      if (this != &e)
05951      _arg_list = e.arg_list();
05952 
05953      return *this;
05954  }
05955 
05956  const List<Expression> &
05957  NonBinaryExpr::arg_list() const
05958  {
05959      return _arg_list;
05960  }
05961 
05962  List<Expression> &
05963  NonBinaryExpr::arg_list()
05964  {
05965      return _arg_list;
05966  }
05967 
05968  const RefList<Expression> *
05969  NonBinaryExpr::arg_refs() const
05970  {
05971      RefList<Expression> *args = new RefList<Expression>;
05972      Iterator<Expression> iter((List<Expression>&) _arg_list);
05973 
05974      for (; iter.valid(); ++iter)
05975      args->ins_last(iter.current());
05976 
05977      return args;
05978  }
05979 
05980  int
05981  NonBinaryExpr::structures_OK() const
05982  {
05983      cerr << "NonBinaryExpr::structures_OK() not implemented";
05984      return True;
05985  }
05986 
05987  int     
05988  NonBinaryExpr::exchange_expr( VDL & vdl )
05989  {
05990      int index = vdl.look_up_expr( *this );
05991 
05992      if (index >= 0)
05993      return index;
05994 
05995      index = Expression::exchange_expr( vdl );
05996 
05997      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
05998 
05999      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
06000 
06001      String opcode;
06002 
06003      switch (this->op()) {
06004      case ADD_OP:    opcode = "+"; break;
06005      case MULT_OP:   opcode = "*"; break;
06006      case OR_OP:     opcode = ".OR."; break;
06007      case AND_OP:    opcode = ".AND."; break;
06008      case EQV_OP:    opcode = ".EQV."; break;
06009      case NEQV_OP:   opcode = ".NEQV."; break;
06010      case COLON_OP:  opcode = ":"; break;
06011      default:  break;
06012      }
06013 
06014      BinRep  *br = new BinRep( new List<BinRep> );
06015      br->to_tuple().ins_last(new BinRep( "op" ));
06016      br->to_tuple().ins_last(new BinRep( opcode ));
06017      S.ins( br );
06018 
06019      br = new BinRep( new List<BinRep> );
06020      br->to_tuple().ins_last(new BinRep( "args" ));
06021      BinRep  *bt = new BinRep(new List<BinRep>);
06022      br->to_tuple().ins_last( bt );
06023      S.ins( br );
06024 
06025      for (Iterator<Expression> iter = _arg_list; iter.valid(); ++iter) {
06026      bt->to_tuple().ins_last(
06027          new BinRep( iter.current().exchange_expr(vdl)));
06028      }
06029 
06030      return index;
06031  }
06032 
06033  void
06034  NonBinaryExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
06035  {
06036      String          s;
06037      BinRep      second;     /// ...  The second argument of tuple pairs
06038 
06039      empty_overflow();
06040 
06041      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
06042                expr_iter.valid(); ++expr_iter) {
06043      String          field;
06044 
06045      expr_iter.current()[0].to_string(field);
06046      second = expr_iter.current()[1];
06047 
06048      if (field == "type")
06049          get_type(second, "NonBinary");
06050      else if (field == "args") {
06051 
06052          for (Iterator<BinRep> iter = second.to_tuple(); 
06053                    iter.valid(); ++iter) {
06054          BinRep  & args = iter.current();
06055 
06056          p_assert( args.is_integer() || args.is_omega(), 
06057                "NonBinaryExpr::convert: "
06058                "Non-Binary Op's arg field contains non-int or OM" );
06059 
06060          Expression *thug = 0;
06061 
06062          if (args.is_integer()) 
06063              thug = tableEntry(args.to_integer());
06064          else if (args.is_omega())
06065              thug = new OmegaExpr;
06066 
06067          _arg_list.ins_last(thug);
06068          }
06069      }
06070      else if (field != "op" && field != "size")
06071          make_overflow(expr_iter, "NonBinaryExpr");
06072      }
06073  }
06074 
06075  void
06076  NonBinaryExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
06077  {
06078      String          s;
06079 
06080      switch (op()) {
06081      case CONCAT_OP:
06082      s = "/// ... ";
06083      break;
06084      case COLON_OP:
06085      s = ":";
06086      break;
06087      case OR_OP:
06088      s = ".OR.";
06089      break;
06090      case AND_OP:
06091      s = ".AND.";
06092      break;
06093      case EQV_OP:
06094      s = ".EQV.";
06095      break;
06096      case NEQV_OP:
06097      s = ".NEQV.";
06098      break;
06099      case ADD_OP:
06100      s = "+";
06101      break;
06102      case MULT_OP:
06103      s = "*";
06104      break;
06105      case COMMA_OP:
06106      s = ", ";
06107      break;
06108      default:
06109      p_abort("Unknown _OP");
06110      }
06111 
06112      print_prec_list( o, op(), _arg_list, s);
06113  }
06114 
06115  void 
06116  NonBinaryExpr::relink_eptrs(ProgramUnit & p)
06117  {
06118      Iterator<Expression>iter = _arg_list;
06119 
06120      for (; iter.valid(); ++iter)
06121      iter.current().relink_eptrs(p);
06122  }
06123 
06124  //-----------------------------------------------------------------------------
06125 /// OmegaExpr code:
06126 ///
06127 
06128  OmegaExpr::~OmegaExpr() 
06129  {
06130      /// ...  nothing to do
06131  }
06132 
06133  OmegaExpr &
06134  OmegaExpr::operator = (const OmegaExpr & NOTUSED(e))
06135  {
06136      return *this;
06137  }
06138 
06139  Expression     *
06140  OmegaExpr::clone() const
06141  {
06142      return new OmegaExpr(*this);
06143  }
06144 
06145  int
06146  OmegaExpr::structures_OK() const
06147  {
06148      cerr << "OmegaExpr::structures_OK() not implemented";
06149      return True;
06150  }
06151 
06152  int     
06153  OmegaExpr::exchange_expr( VDL & vdl )
06154  {
06155      int index = vdl.look_up_expr( *this );
06156 
06157      if (index >= 0)
06158      return index;
06159 
06160      index = Expression::exchange_expr( vdl );
06161 
06162      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
06163 
06164      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
06165 
06166      BinRep  *br = new BinRep( new List<BinRep> );
06167      br->to_tuple().ins_last(new BinRep( "op" ));
06168      br->to_tuple().ins_last(new BinRep( "OMEGA_EXPR" ));
06169      S.ins( br );
06170 
06171      return index;
06172  }
06173 
06174  void
06175  OmegaExpr::convert(BinRep & NOTUSED(exprSet), Symtab & NOTUSED(symtab))
06176  {
06177      /// ...  nothing to do
06178  }
06179 
06180  void
06181  OmegaExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
06182  {
06183      o << "";
06184  }
06185 
06186  //-----------------------------------------------------------------------------
06187 /// GSAExpr code:
06188 ///
06189 
06190 /// Note: The following data fields are aliased:
06191 /// gate = left
06192 /// parameters = right
06193 
06194  GSAExpr::~GSAExpr() 
06195  {
06196      /// ...  nothing to do
06197  }
06198 
06199  Expression     *
06200  GSAExpr::clone() const
06201  {
06202      return new GSAExpr(*this);
06203  }
06204 
06205  GSAExpr &
06206  GSAExpr::operator = (const GSAExpr & e) 
06207  {
06208      BinaryExpr::operator = (e);
06209 
06210      return *this;
06211  }
06212 
06213  void 
06214  GSAExpr::gate(Expression * e)
06215  {
06216      p_assert(!e || e->op() == OMEGA_OP || e->type().data_type() == LOGICAL_TYPE,
06217           "GSAExpr:: gate( ) not an OmegaExpr nor a logical expression ");
06218      _left(null_to_omega(e));
06219  }
06220 
06221  const Expression & 
06222  GSAExpr::gate() const 
06223  {
06224      return _left_guarded();
06225  }
06226 
06227  Expression & 
06228  GSAExpr::gate()
06229  {
06230      return _left_guarded();
06231  }
06232 
06233  void 
06234  GSAExpr::parameters(Expression * e)
06235  {
06236      p_assert(e->op() == COMMA_OP || e->op() == OMEGA_OP,
06237           "GSAExpr:: parameters( ) not an CommaExpr or OmegaExpr");
06238      _right(e);
06239  }
06240 
06241  const Expression & 
06242  GSAExpr::parameters_guarded() const 
06243  {
06244      return _right_guarded();
06245  }
06246 
06247  Expression & 
06248  GSAExpr::parameters_guarded() 
06249  {
06250      return _right_guarded();
06251  }
06252 
06253  Boolean
06254  GSAExpr::parameters_valid() const 
06255  {
06256      return _right_valid();
06257  }
06258 
06259  int
06260  GSAExpr::structures_OK() const
06261  {
06262      cerr << "GSAExpr::structures_OK() not implemented";
06263      return True;
06264  }
06265 
06266  int     
06267  GSAExpr::exchange_expr( VDL & vdl )
06268  {
06269      int index = vdl.look_up_expr( *this );
06270 
06271      if (index >= 0)
06272      return index;
06273 
06274      index = Expression::exchange_expr( vdl );
06275 
06276      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
06277 
06278      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
06279 
06280      BinRep  *br = new BinRep( new List<BinRep> );
06281      br->to_tuple().ins_last(new BinRep( "op" ));
06282      br->to_tuple().ins_last(new BinRep( "GSA_EXPR" ));
06283      S.ins( br );
06284 
06285      return index;
06286  }
06287 
06288  void
06289  GSAExpr::convert(BinRep & NOTUSED(exprSet), Symtab & NOTUSED(symtab))
06290  {
06291      p_abort("GSAExpr::convert() not implemented.");
06292  }
06293 
06294  void
06295  GSAExpr::print_debug(ostream & o, Boolean NOTUSED(debug)) const
06296  {
06297      switch (op()) {
06298      case ALPHA_OP:  o << "ALPHA";    break;
06299      case GAMMA_OP:  o << "GAMMA";  break;
06300      case MU_OP:     o << "MU";     break;
06301      case THETA_OP:  o << "THETA";     break;
06302      case ETA_OP:    o << "ETA";    break;
06303      default: break;
06304      }   
06305 
06306      o << "(";
06307 
06308      if (_left_valid() && _left_guarded().op() != OMEGA_OP) {
06309      print_prec(op(), &_left_guarded(), o);
06310      o << ", ";
06311      }
06312 
06313      print_prec(op(), (_right_valid() ? &_right_guarded() : 0), o);
06314      o << ")";
06315  }
06316 
06317  //-----------------------------------------------------------------------------
06318 /// RealConstExpr code:
06319 ///
06320 
06321  RealConstExpr::~RealConstExpr() 
06322  {
06323      /// ...  nothing to do
06324  }
06325 
06326  RealConstExpr &
06327  RealConstExpr::operator = (const RealConstExpr & e) 
06328  {
06329      StringExpr::operator = (e);
06330 
06331      return *this;
06332  }
06333 
06334  Expression     *
06335  RealConstExpr::clone() const
06336  {
06337      return new RealConstExpr(*this);
06338  }
06339 
06340  int
06341  RealConstExpr::structures_OK() const
06342  {
06343      cerr << "RealConstExpr::structures_OK() not implemented";
06344      return True;
06345  }
06346 
06347  int     
06348  RealConstExpr::exchange_expr( VDL & vdl )
06349  {
06350      int index = vdl.look_up_expr( *this );
06351 
06352      if (index >= 0)
06353      return index;
06354 
06355      index = Expression::exchange_expr( vdl );
06356 
06357      BinRep  *b  = CASTAWAY(BinRep *) vdl.data_ref();
06358 
06359      Set<BinRep> & S = b->find_ref( "expression" )->to_tuple()[index-1].to_set();
06360 
06361      BinRep  *br = new BinRep( new List<BinRep> );
06362      br->to_tuple().ins_last(new BinRep( "op" ));
06363      br->to_tuple().ins_last(new BinRep( "REAL_CONSTANT" ));
06364      S.ins( br );
06365 
06366      br = new BinRep( new List<BinRep> );
06367      br->to_tuple().ins_last(new BinRep( "data" ));
06368      br->to_tuple().ins_last(new BinRep( this->data_ref() ));
06369      S.ins( br );
06370 
06371      return index;
06372  }
06373 
06374  void
06375  RealConstExpr::convert(BinRep & exprSet, Symtab & NOTUSED(symtab))
06376  {
06377      String          s;
06378      BinRep      second;     /// ...  The second argument of tuple pairs
06379 
06380      empty_overflow();
06381 
06382      for (Iterator<BinRep> expr_iter = exprSet.to_set(); 
06383                expr_iter.valid(); ++expr_iter) {
06384      String          field;
06385 
06386      expr_iter.current()[0].to_string(field);
06387      second = expr_iter.current()[1];
06388 
06389      if (field == "type") {
06390          p_assert( second.is_string(),
06391                "RealConstExpr: type field doesn't contain string" );
06392          second.to_string(s);
06393 
06394          if (s == "REAL")
06395          _type = REAL_TYPE;
06396          else if (s == "DOUBLE PRECISION")
06397          _type = DOUBLE_PRECISION_TYPE;
06398          else {
06399          cerr << "RealConstExpr of unexpected type (" << s << ")\n";
06400          p_abort("(See above error message)");
06401          }
06402      }
06403      else if (field == "data") {
06404          p_assert( second.is_string(), "RealConstExpr::convert: "
06405                "'data' field does not contain an string" );
06406          second.to_string(_data);
06407      }
06408      else if (field != "op" && field != "size")
06409          make_overflow(expr_iter, "RealConstExpr");
06410      }
06411  }
06412 
06413  //-----------------------------------------------------------------------------
06414 /// ReturnStarExpr code:
06415 ///
06416 
06417  ReturnStarExpr::~ReturnStarExpr() 
06418  {
06419      /// ...  nothing to do
06420  }
06421 
06422  Expression     *
06423  ReturnStarExpr::clone() const
06424  {
06425      return new ReturnStarExpr(*this);
06426  }
06427 
06428  ReturnStarExpr &
06429  ReturnStarExpr::operator = (const ReturnStarExpr & e) 
06430  {
06431      UnaryExpr::operator = (e);
06432      return *this;
06433  }
06434 
06435  int
06436  ReturnStarExpr::structures_OK() const
06437  {
06438      cerr << "ReturnStar::structures_OK() not implemented";
06439      return True;
06440  }
06441 
06442  int     
06443  ReturnStarExpr::exchange_expr( VDL & vdl )
06444  {
06445      int<