Ignore:
Timestamp:
Dec 16, 2014, 9:41:50 PM (11 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, stuck-waitfor-destruct, with_gc
Children:
17cd4eb
Parents:
3848e0e
Message:

remove Parser.old, add -XCFA to driver, copy ptrdiff_t from stddef.h in preclude, remove casts from initialization constants, adjust formatting

Location:
translator/ResolvExpr
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • translator/ResolvExpr/AdjustExprType.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: AdjustExprType.cc,v 1.3 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    81#include "typeops.h"
    92#include "SynTree/Type.h"
     
    125
    136namespace ResolvExpr {
     7    class AdjustExprType : public Mutator {
     8        typedef Mutator Parent;
     9      public:
     10        AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
     11      private:
     12        virtual Type* mutate(VoidType *voidType);
     13        virtual Type* mutate(BasicType *basicType);
     14        virtual Type* mutate(PointerType *pointerType);
     15        virtual Type* mutate(ArrayType *arrayType);
     16        virtual Type* mutate(FunctionType *functionType);
     17        virtual Type* mutate(StructInstType *aggregateUseType);
     18        virtual Type* mutate(UnionInstType *aggregateUseType);
     19        virtual Type* mutate(EnumInstType *aggregateUseType);
     20        virtual Type* mutate(ContextInstType *aggregateUseType);
     21        virtual Type* mutate(TypeInstType *aggregateUseType);
     22        virtual Type* mutate(TupleType *tupleType);
     23 
     24        const TypeEnvironment &env;
     25        const SymTab::Indexer &indexer;
     26    };
    1427
    15 class AdjustExprType : public Mutator
    16 {
    17   typedef Mutator Parent;
     28    void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     29        AdjustExprType adjuster( env, indexer );
     30        Type *newType = type->acceptMutator( adjuster );
     31        type = newType;
     32    }
    1833
    19 public:
    20   AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
     34    AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer )
     35        : env( env ), indexer( indexer ) {
     36    }
    2137
    22 private:
    23   virtual Type* mutate(VoidType *voidType);
    24   virtual Type* mutate(BasicType *basicType);
    25   virtual Type* mutate(PointerType *pointerType);
    26   virtual Type* mutate(ArrayType *arrayType);
    27   virtual Type* mutate(FunctionType *functionType);
    28   virtual Type* mutate(StructInstType *aggregateUseType);
    29   virtual Type* mutate(UnionInstType *aggregateUseType);
    30   virtual Type* mutate(EnumInstType *aggregateUseType);
    31   virtual Type* mutate(ContextInstType *aggregateUseType);
    32   virtual Type* mutate(TypeInstType *aggregateUseType);
    33   virtual Type* mutate(TupleType *tupleType);
    34  
    35   const TypeEnvironment &env;
    36   const SymTab::Indexer &indexer;
    37 };
     38    Type *AdjustExprType::mutate(VoidType *voidType) {
     39        return voidType;
     40    }
    3841
    39 void
    40 adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    41 {
    42   AdjustExprType adjuster( env, indexer );
    43   Type *newType = type->acceptMutator( adjuster );
    44   type = newType;
    45 }
     42    Type *AdjustExprType::mutate(BasicType *basicType) {
     43        return basicType;
     44    }
    4645
    47 AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    48   : env( env ), indexer( indexer )
    49 {
    50 }
     46    Type *AdjustExprType::mutate(PointerType *pointerType) {
     47        return pointerType;
     48    }
    5149
    52 Type*
    53 AdjustExprType::mutate(VoidType *voidType)
    54 {
    55   return voidType;
    56 }
     50    Type *AdjustExprType::mutate(ArrayType *arrayType) {
     51        PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone() );
     52        delete arrayType;
     53        return pointerType;
     54    }
    5755
    58 Type*
    59 AdjustExprType::mutate(BasicType *basicType)
    60 {
    61   return basicType;
    62 }
     56    Type *AdjustExprType::mutate(FunctionType *functionType) {
     57        PointerType *pointerType = new PointerType( Type::Qualifiers(), functionType );
     58        return pointerType;
     59    }
    6360
    64 Type*
    65 AdjustExprType::mutate(PointerType *pointerType)
    66 {
    67   return pointerType;
    68 }
     61    Type *AdjustExprType::mutate(StructInstType *aggregateUseType) {
     62        return aggregateUseType;
     63    }
    6964
    70 Type*
    71 AdjustExprType::mutate(ArrayType *arrayType)
    72 {
    73   PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone() );
    74   delete arrayType;
    75   return pointerType;
    76 }
     65    Type *AdjustExprType::mutate(UnionInstType *aggregateUseType) {
     66        return aggregateUseType;
     67    }
    7768
    78 Type*
    79 AdjustExprType::mutate(FunctionType *functionType)
    80 {
    81   PointerType *pointerType = new PointerType( Type::Qualifiers(), functionType );
    82   return pointerType;
    83 }
     69    Type *AdjustExprType::mutate(EnumInstType *aggregateUseType) {
     70        return aggregateUseType;
     71    }
    8472
    85 Type*
    86 AdjustExprType::mutate(StructInstType *aggregateUseType)
    87 {
    88   return aggregateUseType;
    89 }
     73    Type *AdjustExprType::mutate(ContextInstType *aggregateUseType) {
     74        return aggregateUseType;
     75    }
    9076
    91 Type*
    92 AdjustExprType::mutate(UnionInstType *aggregateUseType)
    93 {
    94   return aggregateUseType;
    95 }
     77    Type *AdjustExprType::mutate(TypeInstType *typeInst) {
     78        EqvClass eqvClass;
     79        if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
     80            if ( eqvClass.kind == TypeDecl::Ftype ) {
     81                PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
     82                return pointerType;
     83            }
     84        } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
     85            if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
     86                if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
     87                    PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
     88                    return pointerType;
     89                }
     90            }
     91        }
     92        return typeInst;
     93    }
    9694
    97 Type*
    98 AdjustExprType::mutate(EnumInstType *aggregateUseType)
    99 {
    100   return aggregateUseType;
    101 }
    102 
    103 Type*
    104 AdjustExprType::mutate(ContextInstType *aggregateUseType)
    105 {
    106   return aggregateUseType;
    107 }
    108 
    109 Type*
    110 AdjustExprType::mutate(TypeInstType *typeInst)
    111 {
    112   EqvClass eqvClass;
    113   if( env.lookup( typeInst->get_name(), eqvClass ) ) {
    114     if( eqvClass.kind == TypeDecl::Ftype ) {
    115       PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
    116       return pointerType;
     95    Type *AdjustExprType::mutate(TupleType *tupleType) {
     96        return tupleType;
    11797    }
    118   } else if( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    119     if( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
    120       if( tyDecl->get_kind() == TypeDecl::Ftype ) {
    121         PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
    122         return pointerType;
    123       }
    124     }
    125   }
    126   return typeInst;
    127 }
    128 
    129 Type*
    130 AdjustExprType::mutate(TupleType *tupleType)
    131 {
    132   return tupleType;
    133 }
    134 
    135 
    13698} // namespace ResolvExpr
  • translator/ResolvExpr/Alternative.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Alternative.cc,v 1.6 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    81#include "Alternative.h"
    92#include "SynTree/Type.h"
     
    125
    136namespace ResolvExpr {
     7    Alternative::Alternative() : expr( 0 ) {}
    148
    15 Alternative::Alternative()
    16   : expr( 0 )
    17 {
    18 }
     9    Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
     10        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {}
    1911
    20 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
    21   : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env )
    22 {
    23 }
     12    Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
     13        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
    2414
    25 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
    26   : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env )
    27 {
    28 }
     15    Alternative::Alternative( const Alternative &other ) {
     16        initialize( other, *this );
     17    }
    2918
    30 Alternative::Alternative( const Alternative &other )
    31 {
    32   initialize( other, *this );
    33 }
     19    Alternative &Alternative::operator=( const Alternative &other ) {
     20        if ( &other == this ) return *this;
     21        initialize( other, *this );
     22        return *this;
     23    }
    3424
    35 Alternative &
    36 Alternative::operator=( const Alternative &other )
    37 {
    38   if( &other == this ) return *this;
    39   initialize( other, *this );
    40   return *this;
    41 }
     25    void Alternative::initialize( const Alternative &src, Alternative &dest ) {
     26        dest.cost = src.cost;
     27        dest.cvtCost = src.cvtCost;
     28        dest.expr = maybeClone( src.expr );
     29        dest.env = src.env;
     30    }
    4231
    43 void
    44 Alternative::initialize( const Alternative &src, Alternative &dest )
    45 {
    46   dest.cost = src.cost;
    47   dest.cvtCost = src.cvtCost;
    48   dest.expr = maybeClone( src.expr );
    49   dest.env = src.env;
    50 }
     32    Alternative::~Alternative() {
     33        delete expr;
     34    }
    5135
    52 Alternative::~Alternative()
    53 {
    54   delete expr;
    55 }
    56 
    57 void
    58 Alternative::print( std::ostream &os, int indent ) const
    59 {
    60   os << std::string( indent, ' ' ) << "Cost " << cost << ": ";
    61   if( expr ) {
    62     expr->print( os, indent );
    63     os << "(types:" << std::endl;
    64     printAll( expr->get_results(), os, indent + 4 );
    65     os << ")" << std::endl;
    66   } else {
    67     os << "Null expression!" << std::endl;
    68   }
    69   os << std::string( indent, ' ' ) << "Environment: ";
    70   env.print( os, indent+2 );
    71   os << std::endl;
    72 }
    73 
    74 
     36    void Alternative::print( std::ostream &os, int indent ) const {
     37        os << std::string( indent, ' ' ) << "Cost " << cost << ": ";
     38        if ( expr ) {
     39            expr->print( os, indent );
     40            os << "(types:" << std::endl;
     41            printAll( expr->get_results(), os, indent + 4 );
     42            os << ")" << std::endl;
     43        } else {
     44            os << "Null expression!" << std::endl;
     45        }
     46        os << std::string( indent, ' ' ) << "Environment: ";
     47        env.print( os, indent+2 );
     48        os << std::endl;
     49    }
    7550} // namespace ResolvExpr
  • translator/ResolvExpr/Alternative.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Alternative.h,v 1.9 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    81#ifndef RESOLVEXPR_ALTERNATIVE_H
    92#define RESOLVEXPR_ALTERNATIVE_H
     
    158
    169namespace ResolvExpr {
     10    struct Alternative;
     11    typedef std::list< Alternative > AltList;
    1712
    18 struct Alternative;
    19 typedef std::list< Alternative > AltList;
    20 
    21 struct Alternative
    22 {
    23   Alternative();
    24   Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost );
    25   Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost );
    26   Alternative( const Alternative &other );
    27   Alternative &operator=( const Alternative &other );
    28   ~Alternative();
     13    struct Alternative {
     14        Alternative();
     15        Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost );
     16        Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost );
     17        Alternative( const Alternative &other );
     18        Alternative &operator=( const Alternative &other );
     19        ~Alternative();
    2920 
    30   void initialize( const Alternative &src, Alternative &dest );
     21        void initialize( const Alternative &src, Alternative &dest );
    3122 
    32   void print( std::ostream &os, int indent = 0 ) const;
     23        void print( std::ostream &os, int indent = 0 ) const;
    3324 
    34   Cost cost;
    35   Cost cvtCost;
    36   Expression *expr;
    37   TypeEnvironment env;
    38 };
    39 
    40 
     25        Cost cost;
     26        Cost cvtCost;
     27        Expression *expr;
     28        TypeEnvironment env;
     29    };
    4130} // namespace ResolvExpr
    4231
    43 #endif /* #ifndef RESOLVEXPR_ALTERNATIVE_H */
     32#endif // RESOLVEXPR_ALTERNATIVE_H
  • translator/ResolvExpr/AlternativeFinder.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: AlternativeFinder.cc,v 1.36 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    81#include <list>
    92#include <iterator>
     
    3225#include "utility.h"
    3326
    34 
     27extern bool resolveVerbose;
     28#define PRINT( text ) if ( resolveVerbose ) { text }
    3529//#define DEBUG_COST
    3630
    3731namespace ResolvExpr {
    38 
    39 Expression *
    40 resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env )
    41 {
    42   CastExpr *castToVoid = new CastExpr( expr );
    43 
    44   AlternativeFinder finder( indexer, env );
    45   finder.findWithAdjustment( castToVoid );
    46 
    47   // it's a property of the language that a cast expression has either 1 or 0 interpretations;
    48   // if it has 0 interpretations, an exception has already been thrown.
    49   assert( finder.get_alternatives().size() == 1 );
    50   CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );
    51   assert( newExpr );
    52   env = finder.get_alternatives().front().env;
    53   return newExpr->get_arg()->clone();
    54 }
    55 
    56 namespace {
    57 
    58   void
    59   printAlts( const AltList &list, std::ostream &os, int indent = 0 )
    60   {
    61     for( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    62       i->print( os, indent );
    63       os << std::endl;
    64     }
    65   }
    66 
    67   void
    68   makeExprList( const AltList &in, std::list< Expression* > &out )
    69   {
    70     for( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    71       out.push_back( i->expr->clone() );
    72     }
    73   }
    74 
    75   Cost
    76   sumCost( const AltList &in )
    77   {
    78     Cost total;
    79     for( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    80       total += i->cost;
    81     }
    82     return total;
    83   }
    84 
    85   struct PruneStruct
    86   {
    87     bool isAmbiguous;
    88     AltList::iterator candidate;
    89     PruneStruct() {}
    90     PruneStruct( AltList::iterator candidate ): isAmbiguous( false ), candidate( candidate ) {}
    91   };
    92 
    93   template< typename InputIterator, typename OutputIterator >
    94   void
    95   pruneAlternatives( InputIterator begin, InputIterator end, OutputIterator out, const SymTab::Indexer &indexer )
    96   {
    97     // select the alternatives that have the minimum conversion cost for a particular set of result types
    98     std::map< std::string, PruneStruct > selected;
    99     for( AltList::iterator candidate = begin; candidate != end; ++candidate ) {
    100       PruneStruct current( candidate );
    101       std::string mangleName;
    102       for( std::list< Type* >::const_iterator retType = candidate->expr->get_results().begin(); retType != candidate->expr->get_results().end(); ++retType ) {
    103         Type *newType = (*retType)->clone();
    104         candidate->env.apply( newType );
    105         mangleName += SymTab::Mangler::mangle( newType );
    106         delete newType;
    107       }
    108       std::map< std::string, PruneStruct >::iterator mapPlace = selected.find( mangleName );
    109       if( mapPlace != selected.end() ) {
    110         if( candidate->cost < mapPlace->second.candidate->cost ) {
    111 ///           std::cout << "cost " << candidate->cost << " beats " << target->second.cost << std::endl;
    112           selected[ mangleName ] = current;
    113         } else if( candidate->cost == mapPlace->second.candidate->cost ) {
    114 ///           std::cout << "marking ambiguous" << std::endl;
    115           mapPlace->second.isAmbiguous = true;
    116         }
    117       } else {
    118         selected[ mangleName ] = current;
    119       }
    120     }
    121 
    122 ///     std::cout << "there are " << selected.size() << " alternatives before elimination" << std::endl;
    123 
    124     // accept the alternatives that were unambiguous
    125     for( std::map< std::string, PruneStruct >::iterator target = selected.begin(); target != selected.end(); ++target) {
    126       if( !target->second.isAmbiguous ) {
    127         Alternative &alt = *target->second.candidate;
    128         for( std::list< Type* >::iterator result = alt.expr->get_results().begin(); result != alt.expr->get_results().end(); ++result ) {
    129           alt.env.applyFree( *result );
    130         }
    131         *out++ = alt;
    132       }
    133     }
    134 
    135   }
    136 
    137   template< typename InputIterator, typename OutputIterator >
    138   void
    139   findMinCost( InputIterator begin, InputIterator end, OutputIterator out )
    140   {
    141     AltList alternatives;
    142 
    143     // select the alternatives that have the minimum parameter cost
    144     Cost minCost = Cost::infinity;
    145     for( AltList::iterator i = begin; i != end; ++i ) {
    146       if( i->cost < minCost ) {
    147         minCost = i->cost;
    148         i->cost = i->cvtCost;
    149         alternatives.clear();
    150         alternatives.push_back( *i );
    151       } else if( i->cost == minCost ) {
    152         i->cost = i->cvtCost;
    153         alternatives.push_back( *i );
    154       }
    155     }
    156     std::copy( alternatives.begin(), alternatives.end(), out );
    157   }
    158 
    159   template< typename InputIterator >
    160   void
    161   simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result )
    162   {
    163     while( begin != end ) {
    164       result.simpleCombine( (*begin++).env );
    165     }
    166   }
    167 
    168   void
    169   renameTypes( Expression *expr )
    170   {
    171     for( std::list< Type* >::iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
    172       (*i)->accept( global_renamer );
    173     }
    174   }
    175 }
    176 
    177 template< typename InputIterator, typename OutputIterator >
    178 void
    179 AlternativeFinder::findSubExprs( InputIterator begin, InputIterator end, OutputIterator out )
    180 {
    181   while( begin != end ) {
    182     AlternativeFinder finder( indexer, env );
    183     finder.findWithAdjustment( *begin );
    184     // XXX  either this
    185     //Designators::fixDesignations( finder, (*begin++)->get_argName() );
    186     // or XXX this
    187     begin++;
    188 ///     std::cout << "findSubExprs" << std::endl;
    189 ///     printAlts( finder.alternatives, std::cout );
    190     *out++ = finder;
    191   }
    192 }
    193 
    194 AlternativeFinder::AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env )
    195   : indexer( indexer ), env( env )
    196 {
    197 }
    198 
    199 void
    200 AlternativeFinder::find( Expression *expr, bool adjust )
    201 {
    202   expr->accept( *this );
    203   if( alternatives.empty() ) {
    204     throw SemanticError( "No reasonable alternatives for expression ", expr );
    205   }
    206   for( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    207     if( adjust ) {
    208       adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
    209     }
    210   }
    211 ///   std::cout << "alternatives before prune:" << std::endl;
    212 ///   printAlts( alternatives, std::cout );
    213   AltList::iterator oldBegin = alternatives.begin();
    214   pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ), indexer );
    215   if( alternatives.begin() == oldBegin ) {
    216     std::ostrstream stream;
    217     stream << "Can't choose between alternatives for expression ";
    218     expr->print( stream );
    219     stream << "Alternatives are:";
    220     AltList winners;
    221     findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    222     printAlts( winners, stream, 8 );
    223     throw SemanticError( std::string( stream.str(), stream.pcount() ) );
    224   }
    225   alternatives.erase( oldBegin, alternatives.end() );
    226 ///   std::cout << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
    227 }
    228 
    229 void
    230 AlternativeFinder::findWithAdjustment( Expression *expr )
    231 {
    232   find( expr, true );
    233 }
    234 
    235 template< typename StructOrUnionType >
    236 void
    237 AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const std::string &name )
    238 {
    239   std::list< Declaration* > members;
    240   aggInst->lookup( name, members );
    241   for( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    242     if( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    243       alternatives.push_back( Alternative( new MemberExpr( dwt->clone(), expr->clone() ), env, newCost ) );
    244       renameTypes( alternatives.back().expr );
    245     } else {
    246       assert( false );
    247     }
    248   }
    249 }
    250 
    251 void
    252 AlternativeFinder::visit(ApplicationExpr *applicationExpr)
    253 {
    254   alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    255 }
    256 
    257 Cost
    258 computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer )
    259 {
    260   ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( alt.expr );
    261   assert( appExpr );
    262   PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
    263   assert( pointer );
    264   FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
    265   assert( function );
    266 
    267   Cost convCost( 0, 0, 0 );
    268   std::list< DeclarationWithType* >& formals = function->get_parameters();
    269   std::list< DeclarationWithType* >::iterator formal = formals.begin();
    270   std::list< Expression* >& actuals = appExpr->get_args();
    271   for( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    272 ///     std::cout << "actual expression:" << std::endl;
    273 ///     (*actualExpr)->print( std::cout, 8 );
    274 ///     std::cout << "--- results are" << std::endl;
    275 ///     printAll( (*actualExpr)->get_results(), std::cout, 8 );
    276     std::list< DeclarationWithType* >::iterator startFormal = formal;
    277     Cost actualCost;
    278     for( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
    279       if( formal == formals.end() ) {
    280         if( function->get_isVarArgs() ) {
    281           convCost += Cost( 1, 0, 0 );
    282           break;
    283         } else {
    284           return Cost::infinity;
    285         }
    286       }
    287 ///       std::cout << std::endl << "converting ";
    288 ///       (*actual)->print( std::cout, 8 );
    289 ///       std::cout << std::endl << " to ";
    290 ///       (*formal)->get_type()->print( std::cout, 8 );
    291       Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
    292 ///       std::cout << std::endl << "cost is" << newCost << std::endl;
    293 
    294       if( newCost == Cost::infinity ) {
    295         return newCost;
    296       }
    297       convCost += newCost;
    298       actualCost += newCost;
    299 
    300       convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer), 0 );
    301 
    302       formal++;
    303     }
    304     if( actualCost != Cost( 0, 0, 0 ) ) {
    305       std::list< DeclarationWithType* >::iterator startFormalPlusOne = startFormal;
    306       startFormalPlusOne++;
    307       if( formal == startFormalPlusOne ) {
    308         // not a tuple type
    309         Type *newType = (*startFormal)->get_type()->clone();
    310         alt.env.apply( newType );
    311         *actualExpr = new CastExpr( *actualExpr, newType );
    312       } else {
    313         TupleType *newType = new TupleType( Type::Qualifiers() );
    314         for( std::list< DeclarationWithType* >::iterator i = startFormal; i != formal; ++i ) {
    315           newType->get_types().push_back( (*i)->get_type()->clone() );
    316         }
    317         alt.env.apply( newType );
    318         *actualExpr = new CastExpr( *actualExpr, newType );
    319       }
    320     }
    321 
    322   }
    323   if( formal != formals.end() ) {
    324     return Cost::infinity;
    325   }
    326 
    327   for( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
    328 ///     std::cout << std::endl << "converting ";
    329 ///     assert->second.actualType->print( std::cout, 8 );
    330 ///     std::cout << std::endl << " to ";
    331 ///     assert->second.formalType->print( std::cout, 8 );
    332     Cost newCost = conversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    333 ///     std::cout << std::endl << "cost of conversion is " << newCost << std::endl;
    334     if( newCost == Cost::infinity ) {
    335       return newCost;
    336     }
    337     convCost += newCost;
    338 
    339     convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer), 0 );
    340   }
    341 
    342   return convCost;
    343 }
    344 
    345 void
    346 makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions )
    347 {
    348   for( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    349     unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
    350     for( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
    351       needAssertions[ *assert ] = true;
    352     }
     32    Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
     33        CastExpr *castToVoid = new CastExpr( expr );
     34
     35        AlternativeFinder finder( indexer, env );
     36        finder.findWithAdjustment( castToVoid );
     37
     38        // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
     39        // interpretations, an exception has already been thrown.
     40        assert( finder.get_alternatives().size() == 1 );
     41        CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );
     42        assert( newExpr );
     43        env = finder.get_alternatives().front().env;
     44        return newExpr->get_arg()->clone();
     45    }
     46
     47    namespace {
     48        void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
     49            for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
     50                i->print( os, indent );
     51                os << std::endl;
     52            }
     53        }
     54
     55        void makeExprList( const AltList &in, std::list< Expression* > &out ) {
     56            for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
     57                out.push_back( i->expr->clone() );
     58            }
     59        }
     60
     61        Cost sumCost( const AltList &in ) {
     62            Cost total;
     63            for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
     64                total += i->cost;
     65            }
     66            return total;
     67        }
     68
     69        struct PruneStruct {
     70            bool isAmbiguous;
     71            AltList::iterator candidate;
     72            PruneStruct() {}
     73            PruneStruct( AltList::iterator candidate ): isAmbiguous( false ), candidate( candidate ) {}
     74        };
     75
     76        template< typename InputIterator, typename OutputIterator >
     77        void pruneAlternatives( InputIterator begin, InputIterator end, OutputIterator out, const SymTab::Indexer &indexer ) {
     78            // select the alternatives that have the minimum conversion cost for a particular set of result types
     79            std::map< std::string, PruneStruct > selected;
     80            for ( AltList::iterator candidate = begin; candidate != end; ++candidate ) {
     81                PruneStruct current( candidate );
     82                std::string mangleName;
     83                for ( std::list< Type* >::const_iterator retType = candidate->expr->get_results().begin(); retType != candidate->expr->get_results().end(); ++retType ) {
     84                    Type *newType = (*retType)->clone();
     85                    candidate->env.apply( newType );
     86                    mangleName += SymTab::Mangler::mangle( newType );
     87                    delete newType;
     88                }
     89                std::map< std::string, PruneStruct >::iterator mapPlace = selected.find( mangleName );
     90                if ( mapPlace != selected.end() ) {
     91                    if ( candidate->cost < mapPlace->second.candidate->cost ) {
     92                        PRINT(
     93                            std::cout << "cost " << candidate->cost << " beats " << mapPlace->second.candidate->cost << std::endl;
     94                            )
     95                        selected[ mangleName ] = current;
     96                    } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
     97                        PRINT(
     98                            std::cout << "marking ambiguous" << std::endl;
     99                            )
     100                        mapPlace->second.isAmbiguous = true;
     101                    }
     102                } else {
     103                    selected[ mangleName ] = current;
     104                }
     105            }
     106
     107            PRINT(
     108                std::cout << "there are " << selected.size() << " alternatives before elimination" << std::endl;
     109                )
     110
     111            // accept the alternatives that were unambiguous
     112            for ( std::map< std::string, PruneStruct >::iterator target = selected.begin(); target != selected.end(); ++target ) {
     113                if ( !target->second.isAmbiguous ) {
     114                    Alternative &alt = *target->second.candidate;
     115                    for ( std::list< Type* >::iterator result = alt.expr->get_results().begin(); result != alt.expr->get_results().end(); ++result ) {
     116                        alt.env.applyFree( *result );
     117                    }
     118                    *out++ = alt;
     119                }
     120            }
     121
     122        }
     123
     124        template< typename InputIterator, typename OutputIterator >
     125        void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
     126            AltList alternatives;
     127
     128            // select the alternatives that have the minimum parameter cost
     129            Cost minCost = Cost::infinity;
     130            for ( AltList::iterator i = begin; i != end; ++i ) {
     131                if ( i->cost < minCost ) {
     132                    minCost = i->cost;
     133                    i->cost = i->cvtCost;
     134                    alternatives.clear();
     135                    alternatives.push_back( *i );
     136                } else if ( i->cost == minCost ) {
     137                    i->cost = i->cvtCost;
     138                    alternatives.push_back( *i );
     139                }
     140            }
     141            std::copy( alternatives.begin(), alternatives.end(), out );
     142        }
     143
     144        template< typename InputIterator >
     145        void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
     146            while ( begin != end ) {
     147                result.simpleCombine( (*begin++).env );
     148            }
     149        }
     150
     151        void renameTypes( Expression *expr ) {
     152            for ( std::list< Type* >::iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
     153                (*i)->accept( global_renamer );
     154            }
     155        }
     156    }
     157
     158    template< typename InputIterator, typename OutputIterator >
     159    void AlternativeFinder::findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ) {
     160        while ( begin != end ) {
     161            AlternativeFinder finder( indexer, env );
     162            finder.findWithAdjustment( *begin );
     163            // XXX  either this
     164            //Designators::fixDesignations( finder, (*begin++)->get_argName() );
     165            // or XXX this
     166            begin++;
     167            PRINT(
     168                std::cout << "findSubExprs" << std::endl;
     169                printAlts( finder.alternatives, std::cout );
     170                )
     171            *out++ = finder;
     172        }
     173    }
     174
     175    AlternativeFinder::AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env )
     176        : indexer( indexer ), env( env ) {
     177    }
     178
     179    void AlternativeFinder::find( Expression *expr, bool adjust ) {
     180        expr->accept( *this );
     181        if ( alternatives.empty() ) {
     182            throw SemanticError( "No reasonable alternatives for expression ", expr );
     183        }
     184        for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
     185            if ( adjust ) {
     186                adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
     187            }
     188        }
     189        PRINT(
     190            std::cout << "alternatives before prune:" << std::endl;
     191            printAlts( alternatives, std::cout );
     192            )
     193        AltList::iterator oldBegin = alternatives.begin();
     194        pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ), indexer );
     195        if ( alternatives.begin() == oldBegin ) {
     196            std::ostrstream stream;
     197            stream << "Can't choose between alternatives for expression ";
     198            expr->print( stream );
     199            stream << "Alternatives are:";
     200            AltList winners;
     201            findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
     202            printAlts( winners, stream, 8 );
     203            throw SemanticError( std::string( stream.str(), stream.pcount() ) );
     204        }
     205        alternatives.erase( oldBegin, alternatives.end() );
     206        PRINT(
     207            std::cout << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
     208            )
     209    }
     210
     211    void AlternativeFinder::findWithAdjustment( Expression *expr ) {
     212        find( expr, true );
     213    }
     214
     215    template< typename StructOrUnionType >
     216    void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const std::string &name ) {
     217        std::list< Declaration* > members;
     218        aggInst->lookup( name, members );
     219        for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
     220            if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
     221                alternatives.push_back( Alternative( new MemberExpr( dwt->clone(), expr->clone() ), env, newCost ) );
     222                renameTypes( alternatives.back().expr );
     223            } else {
     224                assert( false );
     225            }
     226        }
     227    }
     228
     229    void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
     230        alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     231    }
     232
     233    Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
     234        ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( alt.expr );
     235        assert( appExpr );
     236        PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
     237        assert( pointer );
     238        FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     239        assert( function );
     240
     241        Cost convCost( 0, 0, 0 );
     242        std::list< DeclarationWithType* >& formals = function->get_parameters();
     243        std::list< DeclarationWithType* >::iterator formal = formals.begin();
     244        std::list< Expression* >& actuals = appExpr->get_args();
     245        for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     246            PRINT(
     247                std::cout << "actual expression:" << std::endl;
     248                (*actualExpr)->print( std::cout, 8 );
     249                std::cout << "--- results are" << std::endl;
     250                printAll( (*actualExpr)->get_results(), std::cout, 8 );
     251                )
     252            std::list< DeclarationWithType* >::iterator startFormal = formal;
     253            Cost actualCost;
     254            for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
     255                if ( formal == formals.end() ) {
     256                    if ( function->get_isVarArgs() ) {
     257                        convCost += Cost( 1, 0, 0 );
     258                        break;
     259                    } else {
     260                        return Cost::infinity;
     261                    }
     262                }
     263                PRINT(
     264                    std::cout << std::endl << "converting ";
     265                    (*actual)->print( std::cout, 8 );
     266                    std::cout << std::endl << " to ";
     267                    (*formal)->get_type()->print( std::cout, 8 );
     268                    )
     269                Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
     270                PRINT(
     271                    std::cout << std::endl << "cost is" << newCost << std::endl;
     272                    )
     273
     274                if ( newCost == Cost::infinity ) {
     275                    return newCost;
     276                }
     277                convCost += newCost;
     278                actualCost += newCost;
     279
     280                convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
     281
     282                formal++;
     283            }
     284            if ( actualCost != Cost( 0, 0, 0 ) ) {
     285                std::list< DeclarationWithType* >::iterator startFormalPlusOne = startFormal;
     286                startFormalPlusOne++;
     287                if ( formal == startFormalPlusOne ) {
     288                    // not a tuple type
     289                    Type *newType = (*startFormal)->get_type()->clone();
     290                    alt.env.apply( newType );
     291                    *actualExpr = new CastExpr( *actualExpr, newType );
     292                } else {
     293                    TupleType *newType = new TupleType( Type::Qualifiers() );
     294                    for ( std::list< DeclarationWithType* >::iterator i = startFormal; i != formal; ++i ) {
     295                        newType->get_types().push_back( (*i)->get_type()->clone() );
     296                    }
     297                    alt.env.apply( newType );
     298                    *actualExpr = new CastExpr( *actualExpr, newType );
     299                }
     300            }
     301
     302        }
     303        if ( formal != formals.end() ) {
     304            return Cost::infinity;
     305        }
     306
     307        for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
     308            PRINT(
     309                std::cout << std::endl << "converting ";
     310                assert->second.actualType->print( std::cout, 8 );
     311                std::cout << std::endl << " to ";
     312                assert->second.formalType->print( std::cout, 8 );
     313                )
     314            Cost newCost = conversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
     315            PRINT(
     316                std::cout << std::endl << "cost of conversion is " << newCost << std::endl;
     317                )
     318            if ( newCost == Cost::infinity ) {
     319                return newCost;
     320            }
     321            convCost += newCost;
     322
     323            convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
     324        }
     325
     326        return convCost;
     327    }
     328
     329    void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
     330        for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
     331            unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
     332            for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
     333                needAssertions[ *assert ] = true;
     334            }
    353335///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
    354   }
    355 }
    356 
    357 bool
    358 AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave )
    359 {
    360   std::list< TypeEnvironment > toBeDone;
    361   simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
    362   // make sure we don't widen any existing bindings
    363   for( TypeEnvironment::iterator i = resultEnv.begin(); i != resultEnv.end(); ++i ) {
    364     i->allowWidening  = false;
    365   }
    366   resultEnv.extractOpenVars( openVars );
    367 
    368   /*
    369   Tuples::NameMatcher matcher( formals );
    370   try {
    371     matcher.match( actuals );
    372   } catch ( Tuples::NoMatch &e ) {
    373     std::cerr << "Alternative doesn't match: " << e.message << std::endl;
    374   }
    375   */
    376   std::list< DeclarationWithType* >::iterator formal = formals.begin();
    377   for( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    378     for( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
    379       if( formal == formals.end() ) {
    380         return isVarArgs;
    381       }
    382 ///       std::cerr << "formal type is ";
    383 ///       (*formal)->get_type()->print( std::cerr );
    384 ///       std::cerr << std::endl << "actual type is ";
    385 ///       (*actual)->print( std::cerr );
    386 ///       std::cerr << std::endl;
    387       if( !unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    388         return false;
    389       }
    390       formal++;
    391     }
    392   }
    393   // Handling of default values
    394   while( formal != formals.end() ) {
    395     if( ObjectDecl *od = dynamic_cast<ObjectDecl *>( *formal ) )
    396       if( SingleInit *si = dynamic_cast<SingleInit *>( od->get_init() ))
    397         // so far, only constant expressions are accepted as default values
    398         if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>(si->get_value()) )
    399           if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) )
    400             if( unify( (*formal)->get_type(), cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    401               // XXX Don't know if this is right
    402               actuals.push_back( Alternative( cnstexpr->clone(), env, Cost::zero ) );
    403               formal++;
    404               if (formal == formals.end()) break;
    405             }
    406     return false;
    407   }
    408   return true;
    409 }
    410 
    411 static const int recursionLimit = 10;
    412 
    413 void
    414 addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer )
    415 {
    416   for( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
    417     if( i->second == true ) {
    418       i->first->accept( indexer );
    419     }
    420   }
    421 }
    422 
    423 template< typename ForwardIterator, typename OutputIterator >
    424 void
    425 inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out )
    426 {
    427   if( begin == end ) {
    428     if( newNeed.empty() ) {
    429       *out++ = newAlt;
    430       return;
    431     } else if( level >= recursionLimit ) {
    432       throw SemanticError( "Too many recursive assertions" );
    433     } else {
    434       AssertionSet newerNeed;
    435 ///       std::cerr << "recursing with new set:" << std::endl;
    436 ///       printAssertionSet( newNeed, std::cerr, 8 );
    437       inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    438       return;
    439     }
    440   }
    441 
    442   ForwardIterator cur = begin++;
    443   if( !cur->second ) {
    444     inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    445   }
    446   DeclarationWithType *curDecl = cur->first;
    447 ///   std::cerr << "inferRecursive: assertion is ";
    448 ///   curDecl->print( std::cerr );
    449 ///   std::cerr << std::endl;
    450   std::list< DeclarationWithType* > candidates;
    451   decls.lookupId( curDecl->get_name(), candidates );
    452 ///   if( candidates.empty() ) { std::cout << "no candidates!" << std::endl; }
    453   for( std::list< DeclarationWithType* >::const_iterator candidate = candidates.begin(); candidate != candidates.end(); ++candidate ) {
    454 ///     std::cout << "inferRecursive: candidate is ";
    455 ///     (*candidate)->print( std::cout );
    456 ///     std::cout << std::endl;
    457     AssertionSet newHave, newerNeed( newNeed );
    458     TypeEnvironment newEnv( newAlt.env );
    459     OpenVarSet newOpenVars( openVars );
    460     Type *adjType = (*candidate)->get_type()->clone();
    461     adjustExprType( adjType, newEnv, indexer );
    462     adjType->accept( global_renamer );
    463 ///     std::cerr << "unifying ";
    464 ///     curDecl->get_type()->print( std::cerr );
    465 ///     std::cerr << " with ";
    466 ///     adjType->print( std::cerr );
    467 ///     std::cerr << std::endl;
    468     if( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
    469 ///       std::cerr << "success!" << std::endl;
    470       SymTab::Indexer newDecls( decls );
    471       addToIndexer( newHave, newDecls );
    472       Alternative newerAlt( newAlt );
    473       newerAlt.env = newEnv;
    474       assert( (*candidate)->get_uniqueId() );
    475       Expression *varExpr = new VariableExpr( static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) ) );
    476       deleteAll( varExpr->get_results() );
    477       varExpr->get_results().clear();
    478       varExpr->get_results().push_front( adjType->clone() );
    479 ///       std::cout << "satisfying assertion " << curDecl->get_uniqueId() << " ";
    480 ///       curDecl->print( std::cout );
    481 ///       std::cout << " with declaration " << (*candidate)->get_uniqueId() << " ";
    482 ///       (*candidate)->print( std::cout );
    483 ///       std::cout << std::endl;
    484       ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );
    485       // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    486       appExpr->get_inferParams()[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    487       inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    488     } else {
    489       delete adjType;
    490     }
    491   }
    492 }
    493 
    494 template< typename OutputIterator >
    495 void
    496 AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out )
    497 {
    498 ///   std::cout << "inferParameters: assertions needed are" << std::endl;
    499 ///   printAll( need, std::cout, 8 );
    500   SymTab::Indexer decls( indexer );
    501 ///   std::cout << "============= original indexer" << std::endl;
    502 ///   indexer.print( std::cout );
    503 ///   std::cout << "============= new indexer" << std::endl;
    504 ///   decls.print( std::cout );
    505   addToIndexer( have, decls );
    506   AssertionSet newNeed;
    507   inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    508 ///   std::cout << "declaration 14 is ";
    509 ///   Declaration::declFromId
    510 ///    *out++ = newAlt;
    511 }
    512 
    513 template< typename OutputIterator >
    514 void
    515 AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out )
    516 {
    517   OpenVarSet openVars;
    518   AssertionSet resultNeed, resultHave;
    519   TypeEnvironment resultEnv;
    520   makeUnifiableVars( funcType, openVars, resultNeed );
    521   if( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave ) ) {
    522     ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    523     Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
    524     makeExprList( actualAlt, appExpr->get_args() );
    525 ///     std::cout << "need assertions:" << std::endl;
    526 ///     printAssertionSet( resultNeed, std::cout, 8 );
    527     inferParameters( resultNeed, resultHave, newAlt, openVars, out );
    528   }
    529 }
    530 
    531 void
    532 AlternativeFinder::visit(UntypedExpr *untypedExpr)
    533 {
    534   bool doneInit = false;
    535   AlternativeFinder funcOpFinder( indexer, env );
    536 
    537   AlternativeFinder funcFinder( indexer, env );
    538   {
    539     NameExpr *fname;
    540     if ( (fname = dynamic_cast<NameExpr *>(untypedExpr->get_function()))
    541          && ( fname->get_name() == std::string("LabAddress")) ) {
    542         alternatives.push_back( Alternative(untypedExpr, env, Cost()) );
    543         return;
    544       }
    545   }
    546 
    547   funcFinder.findWithAdjustment( untypedExpr->get_function() );
    548   std::list< AlternativeFinder > argAlternatives;
    549   findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) );
    550 
    551   std::list< AltList > possibilities;
    552   combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    553 
    554   Tuples::TupleAssignSpotter tassign(this);
    555   if ( tassign.isTupleAssignment(untypedExpr, possibilities) ) {
    556     // take care of possible tuple assignments, or discard expression
    557     return;
    558   } // else ...
    559 
    560   AltList candidates;
    561 
    562   for( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    563 ///     std::cout << "working on alternative: " << std::endl;
    564 ///     func->print( std::cout, 8 );
    565     // check if the type is pointer to function
    566     PointerType *pointer;
    567     if( func->expr->get_results().size() == 1 && ( pointer = dynamic_cast< PointerType* >( func->expr->get_results().front() ) ) ) {
    568       if( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    569         for( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    570           // XXX
    571           //Designators::check_alternative( function, *actualAlt );
    572           makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    573         }
    574       } else if( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) {
    575         EqvClass eqvClass;
    576         if( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    577           if( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
    578             for( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    579               makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    580             }
    581           }
    582         }
    583       }
    584     } else {
    585       // seek a function operator that's compatible
    586       if( !doneInit ) {
    587         doneInit = true;
    588         NameExpr *opExpr = new NameExpr( "?()" );
    589         try {
    590           funcOpFinder.findWithAdjustment( opExpr );
    591         } catch( SemanticError &e ) {
    592           // it's ok if there aren't any defined function ops
    593         }
    594 ///         std::cout << "known function ops:" << std::endl;
    595 ///         printAlts( funcOpFinder.alternatives, std::cout, 8 );
    596       }
    597 
    598       for( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    599         // check if the type is pointer to function
    600         PointerType *pointer;
    601         if( funcOp->expr->get_results().size() == 1
    602                 && ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_results().front() ) ) ) {
    603           if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    604             for( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    605               AltList currentAlt;
    606               currentAlt.push_back( *func );
    607               currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
    608               makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
    609             }
    610           }
    611         }
    612       }
    613     }
    614   }
    615 
    616   for( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) {
    617     Cost cvtCost = computeConversionCost( *withFunc, indexer );
    618 
    619 #ifdef DEBUG_COST
    620     ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( withFunc->expr );
    621     assert( appExpr );
    622     PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
    623     assert( pointer );
    624     FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
    625     assert( function );
    626     std::cout << "Case +++++++++++++" << std::endl;
    627     std::cout << "formals are:" << std::endl;
    628     printAll( function->get_parameters(), std::cout, 8 );
    629     std::cout << "actuals are:" << std::endl;
    630     printAll( appExpr->get_args(), std::cout, 8 );
    631     std::cout << "bindings are:" << std::endl;
    632     withFunc->env.print( std::cout, 8 );
    633     std::cout << "cost of conversion is:" << cvtCost << std::endl;
    634 #endif
    635 
    636     if( cvtCost != Cost::infinity ) {
    637       withFunc->cvtCost = cvtCost;
    638       alternatives.push_back( *withFunc );
    639     }
    640   }
    641   candidates.clear();
    642   candidates.splice( candidates.end(), alternatives );
    643 
    644   findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
    645 }
    646 
    647 bool
    648 isLvalue( Expression *expr ) {
    649   for( std::list< Type* >::const_iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
    650     if( !(*i)->get_isLvalue() ) return false;
    651   }
    652   return true;
    653 }
    654 
    655 void
    656 AlternativeFinder::visit(AddressExpr *addressExpr)
    657 {
    658   AlternativeFinder finder( indexer, env );
    659   finder.find( addressExpr->get_arg() );
    660   for( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) {
    661     if( isLvalue( i->expr ) ) {
    662       alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) );
    663     }
    664   }
    665 }
    666 
    667 void
    668 AlternativeFinder::visit(CastExpr *castExpr)
    669 {
    670   for( std::list< Type* >::iterator i = castExpr->get_results().begin(); i != castExpr->get_results().end(); ++i ) {
    671     SymTab::validateType( *i, &indexer );
    672     adjustExprType( *i, env, indexer );
    673   }
    674 
    675   AlternativeFinder finder( indexer, env );
    676   finder.findWithAdjustment( castExpr->get_arg() );
    677 
    678   AltList candidates;
    679   for( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) {
    680     AssertionSet needAssertions, haveAssertions;
    681     OpenVarSet openVars;
    682 
    683     // It's possible that a cast can throw away some values in a multiply-valued expression.
    684     // (An example is a cast-to-void, which casts from one value to zero.)
    685     // Figure out the prefix of the subexpression results that are cast directly.
    686     // The candidate is invalid if it has fewer results than there are types to cast to.
    687     int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
    688     if( discardedValues < 0 ) continue;
    689     std::list< Type* >::iterator candidate_end = (*i).expr->get_results().begin();
    690     std::advance( candidate_end, castExpr->get_results().size() );
    691     if( !unifyList( (*i).expr->get_results().begin(), candidate_end,
    692         castExpr->get_results().begin(), castExpr->get_results().end(), i->env, needAssertions, haveAssertions, openVars, indexer ) ) continue;
    693     Cost thisCost = castCostList( (*i).expr->get_results().begin(), candidate_end,
    694         castExpr->get_results().begin(), castExpr->get_results().end(), indexer, i->env );
    695     if( thisCost != Cost::infinity ) {
    696       // count one safe conversion for each value that is thrown away
    697       thisCost += Cost( 0, 0, discardedValues );
    698       CastExpr *newExpr = castExpr->clone();
    699       newExpr->set_arg( i->expr->clone() );
    700       candidates.push_back( Alternative( newExpr, i->env, i->cost, thisCost ) );
    701     }
    702   }
    703 
    704   // findMinCost selects the alternatives with the lowest "cost" members, but has the side effect
    705   // of copying the cvtCost member to the cost member (since the old cost is now irrelevant).
    706   // Thus, calling findMinCost twice selects first based on argument cost, then on conversion cost.
    707   AltList minArgCost;
    708   findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
    709   findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    710 }
    711 
    712 void
    713 AlternativeFinder::visit(UntypedMemberExpr *memberExpr)
    714 {
    715   AlternativeFinder funcFinder( indexer, env );
    716   funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    717 
    718   for( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    719     if( agg->expr->get_results().size() == 1 ) {
    720       if( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
    721         addAggMembers( structInst, agg->expr, agg->cost, memberExpr->get_member() );
    722       } else if( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
    723         addAggMembers( unionInst, agg->expr, agg->cost, memberExpr->get_member() );
    724       }
    725     }
    726   }
    727 }
    728 
    729 void
    730 AlternativeFinder::visit(MemberExpr *memberExpr)
    731 {
    732   alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    733 }
    734 
    735 void
    736 AlternativeFinder::visit(NameExpr *nameExpr)
    737 {
    738   std::list< DeclarationWithType* > declList;
    739   indexer.lookupId( nameExpr->get_name(), declList );
    740 ///     std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl;
    741   for( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    742     VariableExpr newExpr( *i, nameExpr->get_argName() );
    743     alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
    744 ///     std::cerr << "decl is ";
    745 ///     (*i)->print( std::cerr );
    746 ///     std::cerr << std::endl;
    747 ///     std::cerr << "newExpr is ";
    748 ///     newExpr.print( std::cerr );
    749 ///     std::cerr << std::endl;
    750     renameTypes( alternatives.back().expr );
    751     if( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
    752       addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), "" );
    753     } else if( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
    754       addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), "" );
    755     }
    756   }
    757 }
    758 
    759 void
    760 AlternativeFinder::visit(VariableExpr *variableExpr)
    761 {
    762   alternatives.push_back( Alternative( variableExpr->clone(), env, Cost::zero ) );
    763 }
    764 
    765 void
    766 AlternativeFinder::visit(ConstantExpr *constantExpr)
    767 {
    768   alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    769 }
    770 
    771 void
    772 AlternativeFinder::visit(SizeofExpr *sizeofExpr)
    773 {
    774   if( sizeofExpr->get_isType() ) {
    775     alternatives.push_back( Alternative( sizeofExpr->clone(), env, Cost::zero ) );
    776   } else {
    777     AlternativeFinder finder( indexer, env );
    778     finder.find( sizeofExpr->get_expr() );
    779     if( finder.alternatives.size() != 1 ) {
    780       throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
    781     }
    782     Alternative &choice = finder.alternatives.front();
    783     alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    784   }
    785 }
    786 
    787 void
    788 AlternativeFinder::resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env )
    789 {
    790   // assume no polymorphism
    791   // assume no implicit conversions
    792   assert( function->get_parameters().size() == 1 );
    793 ///   std::cout << "resolvAttr: funcDecl is ";
    794 ///   funcDecl->print( std::cout );
    795 ///   std::cout << " argType is ";
    796 ///   argType->print( std::cout );
    797 ///   std::cout << std::endl;
    798   if( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
    799     alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
    800     for( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
    801       alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
    802     }
    803   }
    804 }
    805 
    806 void
    807 AlternativeFinder::visit(AttrExpr *attrExpr)
    808 {
    809   // assume no 'pointer-to-attribute'
    810   NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
    811   assert( nameExpr );
    812   std::list< DeclarationWithType* > attrList;
    813   indexer.lookupId( nameExpr->get_name(), attrList );
    814   if( attrExpr->get_isType() || attrExpr->get_expr() ) {
    815     for( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    816       // check if the type is function
    817       if( FunctionType *function = dynamic_cast< FunctionType* >( (*i)->get_type() ) ) {
    818         // assume exactly one parameter
    819         if( function->get_parameters().size() == 1 ) {
    820           if( attrExpr->get_isType() ) {
    821             resolveAttr( *i, function, attrExpr->get_type(), env );
    822           } else {
    823             AlternativeFinder finder( indexer, env );
    824             finder.find( attrExpr->get_expr() );
    825             for( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    826               if( choice->expr->get_results().size() == 1 ) {
    827                 resolveAttr(*i, function, choice->expr->get_results().front(), choice->env );
    828               }
    829             }
    830           }
    831         }
    832       }
    833     }
    834   } else {
    835     for( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    836       VariableExpr newExpr( *i );
    837       alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
    838       renameTypes( alternatives.back().expr );
    839     }
    840   }
    841 }
    842 
    843 void
    844 AlternativeFinder::visit(LogicalExpr *logicalExpr)
    845 {
    846   AlternativeFinder firstFinder( indexer, env );
    847   firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
    848   for( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    849     AlternativeFinder secondFinder( indexer, first->env );
    850     secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
    851     for( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    852       LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() );
    853       alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) );
    854     }
    855   }
    856 }
    857 
    858 void
    859 AlternativeFinder::visit(ConditionalExpr *conditionalExpr)
    860 {
    861   AlternativeFinder firstFinder( indexer, env );
    862   firstFinder.findWithAdjustment( conditionalExpr->get_arg1() );
    863   for( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    864     AlternativeFinder secondFinder( indexer, first->env );
    865     secondFinder.findWithAdjustment( conditionalExpr->get_arg2() );
    866     for( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    867       AlternativeFinder thirdFinder( indexer, second->env );
    868       thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() );
    869       for( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) {
    870         OpenVarSet openVars;
    871         AssertionSet needAssertions, haveAssertions;
    872         Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
    873         std::list< Type* > commonTypes;
    874         if( unifyList( second->expr->get_results().begin(), second->expr->get_results().end(), third->expr->get_results().begin(), third->expr->get_results().end(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
    875           ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    876           std::list< Type* >::const_iterator original = second->expr->get_results().begin();
    877           std::list< Type* >::const_iterator commonType = commonTypes.begin();
    878           for( ; original != second->expr->get_results().end() && commonType != commonTypes.end(); ++original, ++commonType ) {
    879             if( *commonType ) {
    880               newExpr->get_results().push_back( *commonType );
    881             } else {
    882               newExpr->get_results().push_back( (*original)->clone() );
    883             }
    884           }
    885           newAlt.expr = newExpr;
    886           inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    887         }
    888       }
    889     }
    890   }
    891 }
    892 
    893 void
    894 AlternativeFinder::visit(CommaExpr *commaExpr)
    895 {
    896   TypeEnvironment newEnv( env );
    897   Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
    898   AlternativeFinder secondFinder( indexer, newEnv );
    899   secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    900   for( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt ) {
    901     alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt->expr->clone() ), alt->env, alt->cost ) );
    902   }
    903   delete newFirstArg;
    904 }
    905 
    906 void
    907 AlternativeFinder::visit(TupleExpr *tupleExpr)
    908 {
    909   std::list< AlternativeFinder > subExprAlternatives;
    910   findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) );
    911   std::list< AltList > possibilities;
    912   combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) );
    913   for( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) {
    914     TupleExpr *newExpr = new TupleExpr;
    915     makeExprList( *i, newExpr->get_exprs() );
    916     for( std::list< Expression* >::const_iterator resultExpr = newExpr->get_exprs().begin(); resultExpr != newExpr->get_exprs().end(); ++resultExpr ) {
    917       for( std::list< Type* >::const_iterator resultType = (*resultExpr)->get_results().begin(); resultType != (*resultExpr)->get_results().end(); ++resultType ) {
    918         newExpr->get_results().push_back( (*resultType)->clone() );
    919       }
    920     }
    921 
    922     TypeEnvironment compositeEnv;
    923     simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
    924     alternatives.push_back( Alternative( newExpr, compositeEnv, sumCost( *i ) ) );
    925   }
    926 }
    927 
     336        }
     337    }
     338
     339    bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave ) {
     340        std::list< TypeEnvironment > toBeDone;
     341        simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
     342        // make sure we don't widen any existing bindings
     343        for ( TypeEnvironment::iterator i = resultEnv.begin(); i != resultEnv.end(); ++i ) {
     344            i->allowWidening  = false;
     345        }
     346        resultEnv.extractOpenVars( openVars );
     347
     348        /*
     349          Tuples::NameMatcher matcher( formals );
     350          try {
     351          matcher.match( actuals );
     352          } catch ( Tuples::NoMatch &e ) {
     353          std::cerr << "Alternative doesn't match: " << e.message << std::endl;
     354          }
     355        */
     356        std::list< DeclarationWithType* >::iterator formal = formals.begin();
     357        for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     358            for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
     359                if ( formal == formals.end() ) {
     360                    return isVarArgs;
     361                }
     362                PRINT(
     363                    std::cerr << "formal type is ";
     364                    (*formal)->get_type()->print( std::cerr );
     365                    std::cerr << std::endl << "actual type is ";
     366                    (*actual)->print( std::cerr );
     367                    std::cerr << std::endl;
     368                    )
     369                if ( !unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     370                    return false;
     371                }
     372                formal++;
     373            }
     374        }
     375        // Handling of default values
     376        while ( formal != formals.end() ) {
     377            if ( ObjectDecl *od = dynamic_cast<ObjectDecl *>( *formal ) )
     378                if ( SingleInit *si = dynamic_cast<SingleInit *>( od->get_init() ))
     379                    // so far, only constant expressions are accepted as default values
     380                    if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) )
     381                        if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) )
     382                            if ( unify( (*formal)->get_type(), cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     383                                // XXX Don't know if this is right
     384                                actuals.push_back( Alternative( cnstexpr->clone(), env, Cost::zero ) );
     385                                formal++;
     386                                if ( formal == formals.end()) break;
     387                            }
     388            return false;
     389        }
     390        return true;
     391    }
     392
     393    static const int recursionLimit = 10;
     394
     395    void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     396        for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
     397            if ( i->second == true ) {
     398                i->first->accept( indexer );
     399            }
     400        }
     401    }
     402
     403    template< typename ForwardIterator, typename OutputIterator >
     404    void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     405        if ( begin == end ) {
     406            if ( newNeed.empty() ) {
     407                *out++ = newAlt;
     408                return;
     409            } else if ( level >= recursionLimit ) {
     410                throw SemanticError( "Too many recursive assertions" );
     411            } else {
     412                AssertionSet newerNeed;
     413                PRINT(
     414                    std::cerr << "recursing with new set:" << std::endl;
     415                    printAssertionSet( newNeed, std::cerr, 8 );
     416                    )
     417                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
     418                return;
     419            }
     420        }
     421
     422        ForwardIterator cur = begin++;
     423        if ( !cur->second ) {
     424            inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
     425        }
     426        DeclarationWithType *curDecl = cur->first;
     427        PRINT(
     428            std::cerr << "inferRecursive: assertion is ";
     429            curDecl->print( std::cerr );
     430            std::cerr << std::endl;
     431            )
     432        std::list< DeclarationWithType* > candidates;
     433        decls.lookupId( curDecl->get_name(), candidates );
     434///   if ( candidates.empty() ) { std::cout << "no candidates!" << std::endl; }
     435        for ( std::list< DeclarationWithType* >::const_iterator candidate = candidates.begin(); candidate != candidates.end(); ++candidate ) {
     436            PRINT(
     437                std::cout << "inferRecursive: candidate is ";
     438                (*candidate)->print( std::cout );
     439                std::cout << std::endl;
     440                )
     441            AssertionSet newHave, newerNeed( newNeed );
     442            TypeEnvironment newEnv( newAlt.env );
     443            OpenVarSet newOpenVars( openVars );
     444            Type *adjType = (*candidate)->get_type()->clone();
     445            adjustExprType( adjType, newEnv, indexer );
     446            adjType->accept( global_renamer );
     447            PRINT(
     448                std::cerr << "unifying ";
     449                curDecl->get_type()->print( std::cerr );
     450                std::cerr << " with ";
     451                adjType->print( std::cerr );
     452                std::cerr << std::endl;
     453                )
     454            if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
     455                PRINT(
     456                    std::cerr << "success!" << std::endl;
     457                    )
     458                SymTab::Indexer newDecls( decls );
     459                addToIndexer( newHave, newDecls );
     460                Alternative newerAlt( newAlt );
     461                newerAlt.env = newEnv;
     462                assert( (*candidate)->get_uniqueId() );
     463                Expression *varExpr = new VariableExpr( static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) ) );
     464                deleteAll( varExpr->get_results() );
     465                varExpr->get_results().clear();
     466                varExpr->get_results().push_front( adjType->clone() );
     467                PRINT(
     468                    std::cout << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     469                    curDecl->print( std::cout );
     470                    std::cout << " with declaration " << (*candidate)->get_uniqueId() << " ";
     471                    (*candidate)->print( std::cout );
     472                    std::cout << std::endl;
     473                    )
     474                ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );
     475                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
     476                appExpr->get_inferParams()[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
     477                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
     478            } else {
     479                delete adjType;
     480            }
     481        }
     482    }
     483
     484    template< typename OutputIterator >
     485    void AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     486//      PRINT(
     487//          std::cout << "inferParameters: assertions needed are" << std::endl;
     488//          printAll( need, std::cout, 8 );
     489//          )
     490        SymTab::Indexer decls( indexer );
     491        PRINT(
     492            std::cout << "============= original indexer" << std::endl;
     493            indexer.print( std::cout );
     494            std::cout << "============= new indexer" << std::endl;
     495            decls.print( std::cout );
     496            )
     497        addToIndexer( have, decls );
     498        AssertionSet newNeed;
     499        inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
     500//      PRINT(
     501//          std::cout << "declaration 14 is ";
     502//          Declaration::declFromId
     503//          *out++ = newAlt;
     504//          )
     505    }
     506
     507    template< typename OutputIterator >
     508    void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out ) {
     509        OpenVarSet openVars;
     510        AssertionSet resultNeed, resultHave;
     511        TypeEnvironment resultEnv;
     512        makeUnifiableVars( funcType, openVars, resultNeed );
     513        if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave ) ) {
     514            ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
     515            Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
     516            makeExprList( actualAlt, appExpr->get_args() );
     517            PRINT(
     518                std::cout << "need assertions:" << std::endl;
     519                printAssertionSet( resultNeed, std::cout, 8 );
     520                )
     521            inferParameters( resultNeed, resultHave, newAlt, openVars, out );
     522        }
     523    }
     524
     525    void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
     526        bool doneInit = false;
     527        AlternativeFinder funcOpFinder( indexer, env );
     528
     529        AlternativeFinder funcFinder( indexer, env ); {
     530            NameExpr *fname;
     531            if ( ( fname = dynamic_cast<NameExpr *>( untypedExpr->get_function()))
     532                 && ( fname->get_name() == std::string("LabAddress")) ) {
     533                alternatives.push_back( Alternative( untypedExpr, env, Cost()) );
     534                return;
     535            }
     536        }
     537
     538        funcFinder.findWithAdjustment( untypedExpr->get_function() );
     539        std::list< AlternativeFinder > argAlternatives;
     540        findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) );
     541
     542        std::list< AltList > possibilities;
     543        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
     544
     545        Tuples::TupleAssignSpotter tassign( this );
     546        if ( tassign.isTupleAssignment( untypedExpr, possibilities ) ) {
     547            // take care of possible tuple assignments, or discard expression
     548            return;
     549        } // else ...
     550
     551        AltList candidates;
     552
     553        for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
     554            PRINT(
     555                std::cout << "working on alternative: " << std::endl;
     556                func->print( std::cout, 8 );
     557                )
     558            // check if the type is pointer to function
     559            PointerType *pointer;
     560            if ( func->expr->get_results().size() == 1 && ( pointer = dynamic_cast< PointerType* >( func->expr->get_results().front() ) ) ) {
     561                if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     562                    for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     563                        // XXX
     564                        //Designators::check_alternative( function, *actualAlt );
     565                        makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     566                    }
     567                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) {
     568                    EqvClass eqvClass;
     569                    if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
     570                        if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     571                            for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     572                                makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     573                            }
     574                        }
     575                    }
     576                }
     577            } else {
     578                // seek a function operator that's compatible
     579                if ( !doneInit ) {
     580                    doneInit = true;
     581                    NameExpr *opExpr = new NameExpr( "?()" );
     582                    try {
     583                        funcOpFinder.findWithAdjustment( opExpr );
     584                    } catch( SemanticError &e ) {
     585                        // it's ok if there aren't any defined function ops
     586                    }
     587                    PRINT(
     588                        std::cout << "known function ops:" << std::endl;
     589                        printAlts( funcOpFinder.alternatives, std::cout, 8 );
     590                        )
     591                }
     592
     593                for ( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     594                    // check if the type is pointer to function
     595                    PointerType *pointer;
     596                    if ( funcOp->expr->get_results().size() == 1
     597                        && ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_results().front() ) ) ) {
     598                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     599                            for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     600                                AltList currentAlt;
     601                                currentAlt.push_back( *func );
     602                                currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
     603                                makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
     604                            }
     605                        }
     606                    }
     607                }
     608            }
     609        }
     610
     611        for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) {
     612            Cost cvtCost = computeConversionCost( *withFunc, indexer );
     613
     614            PRINT(
     615                ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( withFunc->expr );
     616                assert( appExpr );
     617                PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
     618                assert( pointer );
     619                FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     620                assert( function );
     621                std::cout << "Case +++++++++++++" << std::endl;
     622                std::cout << "formals are:" << std::endl;
     623                printAll( function->get_parameters(), std::cout, 8 );
     624                std::cout << "actuals are:" << std::endl;
     625                printAll( appExpr->get_args(), std::cout, 8 );
     626                std::cout << "bindings are:" << std::endl;
     627                withFunc->env.print( std::cout, 8 );
     628                std::cout << "cost of conversion is:" << cvtCost << std::endl;
     629                )
     630            if ( cvtCost != Cost::infinity ) {
     631                withFunc->cvtCost = cvtCost;
     632                alternatives.push_back( *withFunc );
     633            }
     634        }
     635        candidates.clear();
     636        candidates.splice( candidates.end(), alternatives );
     637
     638        findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
     639    }
     640
     641    bool isLvalue( Expression *expr ) {
     642        for ( std::list< Type* >::const_iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
     643            if ( !(*i)->get_isLvalue() ) return false;
     644        }
     645        return true;
     646    }
     647
     648    void AlternativeFinder::visit( AddressExpr *addressExpr ) {
     649        AlternativeFinder finder( indexer, env );
     650        finder.find( addressExpr->get_arg() );
     651        for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) {
     652            if ( isLvalue( i->expr ) ) {
     653                alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) );
     654            }
     655        }
     656    }
     657
     658    void AlternativeFinder::visit( CastExpr *castExpr ) {
     659        for ( std::list< Type* >::iterator i = castExpr->get_results().begin(); i != castExpr->get_results().end(); ++i ) {
     660            SymTab::validateType( *i, &indexer );
     661            adjustExprType( *i, env, indexer );
     662        }
     663
     664        AlternativeFinder finder( indexer, env );
     665        finder.findWithAdjustment( castExpr->get_arg() );
     666
     667        AltList candidates;
     668        for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) {
     669            AssertionSet needAssertions, haveAssertions;
     670            OpenVarSet openVars;
     671
     672            // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
     673            // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
     674            // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
     675            // to.
     676            int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
     677            if ( discardedValues < 0 ) continue;
     678            std::list< Type* >::iterator candidate_end = (*i).expr->get_results().begin();
     679            std::advance( candidate_end, castExpr->get_results().size() );
     680            if ( !unifyList( (*i).expr->get_results().begin(), candidate_end,
     681                            castExpr->get_results().begin(), castExpr->get_results().end(), i->env, needAssertions, haveAssertions, openVars, indexer ) ) continue;
     682            Cost thisCost = castCostList( (*i).expr->get_results().begin(), candidate_end,
     683                                          castExpr->get_results().begin(), castExpr->get_results().end(), indexer, i->env );
     684            if ( thisCost != Cost::infinity ) {
     685                // count one safe conversion for each value that is thrown away
     686                thisCost += Cost( 0, 0, discardedValues );
     687                CastExpr *newExpr = castExpr->clone();
     688                newExpr->set_arg( i->expr->clone() );
     689                candidates.push_back( Alternative( newExpr, i->env, i->cost, thisCost ) );
     690            }
     691        }
     692
     693        // findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the
     694        // cvtCost member to the cost member (since the old cost is now irrelevant).  Thus, calling findMinCost twice
     695        // selects first based on argument cost, then on conversion cost.
     696        AltList minArgCost;
     697        findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
     698        findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
     699    }
     700
     701    void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) {
     702        AlternativeFinder funcFinder( indexer, env );
     703        funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
     704
     705        for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
     706            if ( agg->expr->get_results().size() == 1 ) {
     707                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
     708                    addAggMembers( structInst, agg->expr, agg->cost, memberExpr->get_member() );
     709                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
     710                    addAggMembers( unionInst, agg->expr, agg->cost, memberExpr->get_member() );
     711                }
     712            }
     713        }
     714    }
     715
     716    void AlternativeFinder::visit( MemberExpr *memberExpr ) {
     717        alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     718    }
     719
     720    void AlternativeFinder::visit( NameExpr *nameExpr ) {
     721        std::list< DeclarationWithType* > declList;
     722        indexer.lookupId( nameExpr->get_name(), declList );
     723        PRINT(
     724            std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl;
     725            )
     726        for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
     727            VariableExpr newExpr( *i, nameExpr->get_argName() );
     728            alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     729            PRINT(
     730                std::cerr << "decl is ";
     731                (*i)->print( std::cerr );
     732                std::cerr << std::endl;
     733                std::cerr << "newExpr is ";
     734                newExpr.print( std::cerr );
     735                std::cerr << std::endl;
     736                )
     737            renameTypes( alternatives.back().expr );
     738            if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
     739                addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), "" );
     740            } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
     741                addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), "" );
     742            }
     743        }
     744    }
     745
     746    void AlternativeFinder::visit( VariableExpr *variableExpr ) {
     747        alternatives.push_back( Alternative( variableExpr->clone(), env, Cost::zero ) );
     748    }
     749
     750    void AlternativeFinder::visit( ConstantExpr *constantExpr ) {
     751        alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     752    }
     753
     754    void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) {
     755        if ( sizeofExpr->get_isType() ) {
     756            alternatives.push_back( Alternative( sizeofExpr->clone(), env, Cost::zero ) );
     757        } else {
     758            AlternativeFinder finder( indexer, env );
     759            finder.find( sizeofExpr->get_expr() );
     760            if ( finder.alternatives.size() != 1 ) {
     761                throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
     762            }
     763            Alternative &choice = finder.alternatives.front();
     764            alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     765        }
     766    }
     767
     768    void AlternativeFinder::resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env ) {
     769        // assume no polymorphism
     770        // assume no implicit conversions
     771        assert( function->get_parameters().size() == 1 );
     772        PRINT(
     773            std::cout << "resolvAttr: funcDecl is ";
     774            funcDecl->print( std::cout );
     775            std::cout << " argType is ";
     776            argType->print( std::cout );
     777            std::cout << std::endl;
     778            )
     779        if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
     780            alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
     781            for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
     782                alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
     783            }
     784        }
     785    }
     786
     787    void AlternativeFinder::visit( AttrExpr *attrExpr ) {
     788        // assume no 'pointer-to-attribute'
     789        NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
     790        assert( nameExpr );
     791        std::list< DeclarationWithType* > attrList;
     792        indexer.lookupId( nameExpr->get_name(), attrList );
     793        if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
     794            for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
     795                // check if the type is function
     796                if ( FunctionType *function = dynamic_cast< FunctionType* >( (*i)->get_type() ) ) {
     797                    // assume exactly one parameter
     798                    if ( function->get_parameters().size() == 1 ) {
     799                        if ( attrExpr->get_isType() ) {
     800                            resolveAttr( *i, function, attrExpr->get_type(), env );
     801                        } else {
     802                            AlternativeFinder finder( indexer, env );
     803                            finder.find( attrExpr->get_expr() );
     804                            for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
     805                                if ( choice->expr->get_results().size() == 1 ) {
     806                                    resolveAttr(*i, function, choice->expr->get_results().front(), choice->env );
     807                                }
     808                            }
     809                        }
     810                    }
     811                }
     812            }
     813        } else {
     814            for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
     815                VariableExpr newExpr( *i );
     816                alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     817                renameTypes( alternatives.back().expr );
     818            }
     819        }
     820    }
     821
     822    void AlternativeFinder::visit( LogicalExpr *logicalExpr ) {
     823        AlternativeFinder firstFinder( indexer, env );
     824        firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
     825        for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
     826            AlternativeFinder secondFinder( indexer, first->env );
     827            secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
     828            for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     829                LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() );
     830                alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) );
     831            }
     832        }
     833    }
     834
     835    void AlternativeFinder::visit( ConditionalExpr *conditionalExpr ) {
     836        AlternativeFinder firstFinder( indexer, env );
     837        firstFinder.findWithAdjustment( conditionalExpr->get_arg1() );
     838        for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
     839            AlternativeFinder secondFinder( indexer, first->env );
     840            secondFinder.findWithAdjustment( conditionalExpr->get_arg2() );
     841            for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     842                AlternativeFinder thirdFinder( indexer, second->env );
     843                thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() );
     844                for ( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) {
     845                    OpenVarSet openVars;
     846                    AssertionSet needAssertions, haveAssertions;
     847                    Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
     848                    std::list< Type* > commonTypes;
     849                    if ( unifyList( second->expr->get_results().begin(), second->expr->get_results().end(), third->expr->get_results().begin(), third->expr->get_results().end(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
     850                        ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
     851                        std::list< Type* >::const_iterator original = second->expr->get_results().begin();
     852                        std::list< Type* >::const_iterator commonType = commonTypes.begin();
     853                        for ( ; original != second->expr->get_results().end() && commonType != commonTypes.end(); ++original, ++commonType ) {
     854                            if ( *commonType ) {
     855                                newExpr->get_results().push_back( *commonType );
     856                            } else {
     857                                newExpr->get_results().push_back( (*original)->clone() );
     858                            }
     859                        }
     860                        newAlt.expr = newExpr;
     861                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     862                    }
     863                }
     864            }
     865        }
     866    }
     867
     868    void AlternativeFinder::visit( CommaExpr *commaExpr ) {
     869        TypeEnvironment newEnv( env );
     870        Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
     871        AlternativeFinder secondFinder( indexer, newEnv );
     872        secondFinder.findWithAdjustment( commaExpr->get_arg2() );
     873        for ( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt ) {
     874            alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt->expr->clone() ), alt->env, alt->cost ) );
     875        }
     876        delete newFirstArg;
     877    }
     878
     879    void AlternativeFinder::visit( TupleExpr *tupleExpr ) {
     880        std::list< AlternativeFinder > subExprAlternatives;
     881        findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) );
     882        std::list< AltList > possibilities;
     883        combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) );
     884        for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) {
     885            TupleExpr *newExpr = new TupleExpr;
     886            makeExprList( *i, newExpr->get_exprs() );
     887            for ( std::list< Expression* >::const_iterator resultExpr = newExpr->get_exprs().begin(); resultExpr != newExpr->get_exprs().end(); ++resultExpr ) {
     888                for ( std::list< Type* >::const_iterator resultType = (*resultExpr)->get_results().begin(); resultType != (*resultExpr)->get_results().end(); ++resultType ) {
     889                    newExpr->get_results().push_back( (*resultType)->clone() );
     890                }
     891            }
     892
     893            TypeEnvironment compositeEnv;
     894            simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
     895            alternatives.push_back( Alternative( newExpr, compositeEnv, sumCost( *i ) ) );
     896        }
     897    }
    928898} // namespace ResolvExpr
  • translator/ResolvExpr/AlternativeFinder.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: AlternativeFinder.h,v 1.19 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    8 #ifndef RESOLVEXPR_ALTERNATIVEFINDER_H
    9 #define RESOLVEXPR_ALTERNATIVEFINDER_H
     1#ifndef ALTERNATIVEFINDER_H
     2#define ALTERNATIVEFINDER_H
    103
    114#include <set>
     
    1811
    1912namespace ResolvExpr {
     13    class AlternativeFinder : public Visitor {
     14      public:
     15        AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env );
     16        void find( Expression *expr, bool adjust = false );
     17        void findWithAdjustment( Expression *expr );
     18        AltList &get_alternatives() { return alternatives; }
     19 
     20        // make this look like an STL container so that we can apply generic algorithms
     21        typedef Alternative value_type;
     22        typedef AltList::iterator iterator;
     23        typedef AltList::const_iterator const_iterator;
     24        AltList::iterator begin() { return alternatives.begin(); }
     25        AltList::iterator end() { return alternatives.end(); }
     26        AltList::const_iterator begin() const { return alternatives.begin(); }
     27        AltList::const_iterator end() const { return alternatives.end(); }
     28 
     29        const SymTab::Indexer &get_indexer() const { return indexer; }
     30        const TypeEnvironment &get_environ() const { return env; }
     31      private:
     32        virtual void visit( ApplicationExpr *applicationExpr );
     33        virtual void visit( UntypedExpr *untypedExpr );
     34        virtual void visit( AddressExpr *addressExpr );
     35        virtual void visit( CastExpr *castExpr );
     36        virtual void visit( UntypedMemberExpr *memberExpr );
     37        virtual void visit( MemberExpr *memberExpr );
     38        virtual void visit( NameExpr *variableExpr );
     39        virtual void visit( VariableExpr *variableExpr );
     40        virtual void visit( ConstantExpr *constantExpr );
     41        virtual void visit( SizeofExpr *sizeofExpr );
     42        virtual void visit( AttrExpr *attrExpr );
     43        virtual void visit( LogicalExpr *logicalExpr );
     44        virtual void visit( ConditionalExpr *conditionalExpr );
     45        virtual void visit( CommaExpr *commaExpr );
     46        virtual void visit( TupleExpr *tupleExpr );
     47      public:  // xxx - temporary hack - should make Tuples::TupleAssignment a friend
     48        template< typename InputIterator, typename OutputIterator >
     49            void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    2050
    21 class AlternativeFinder : public Visitor
    22 {
    23 public:
    24   AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env );
    25   void find( Expression *expr, bool adjust = false );
    26   void findWithAdjustment( Expression *expr );
    27   AltList &get_alternatives() { return alternatives; }
    28  
    29   // make this look like an STL container so that we can apply generic algorithms
    30   typedef Alternative value_type;
    31   typedef AltList::iterator iterator;
    32   typedef AltList::const_iterator const_iterator;
    33   AltList::iterator begin() { return alternatives.begin(); }
    34   AltList::iterator end() { return alternatives.end(); }
    35   AltList::const_iterator begin() const { return alternatives.begin(); }
    36   AltList::const_iterator end() const { return alternatives.end(); }
    37  
    38   const SymTab::Indexer &get_indexer() const { return indexer; }
    39   const TypeEnvironment &get_environ() const { return env; }
    40 private:
    41   virtual void visit(ApplicationExpr *applicationExpr);
    42   virtual void visit(UntypedExpr *untypedExpr);
    43   virtual void visit(AddressExpr *addressExpr);
    44   virtual void visit(CastExpr *castExpr);
    45   virtual void visit(UntypedMemberExpr *memberExpr);
    46   virtual void visit(MemberExpr *memberExpr);
    47   virtual void visit(NameExpr *variableExpr);
    48   virtual void visit(VariableExpr *variableExpr);
    49   virtual void visit(ConstantExpr *constantExpr);
    50   virtual void visit(SizeofExpr *sizeofExpr);
    51   virtual void visit(AttrExpr *attrExpr);
    52   virtual void visit(LogicalExpr *logicalExpr);
    53   virtual void visit(ConditionalExpr *conditionalExpr);
    54   virtual void visit(CommaExpr *commaExpr);
    55   virtual void visit(TupleExpr *tupleExpr);
    56  public:  // xxx - temporary hack - should make Tuples::TupleAssignment a friend
    57   template< typename InputIterator, typename OutputIterator >
    58   void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
     51      private:
     52        template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const std::string &name );
     53        bool instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave );
     54        template< typename OutputIterator >
     55            void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out );
     56        template< typename OutputIterator >
     57            void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     58        void resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env );
    5959
    60  private:
    61   template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const std::string &name );
    62   bool instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave );
    63   template< typename OutputIterator >
    64   void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out );
    65   template< typename OutputIterator >
    66   void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    67   void resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env );
     60        const SymTab::Indexer &indexer;
     61        AltList alternatives;
     62        const TypeEnvironment &env;
     63    }; // AlternativeFinder
    6864
    69   const SymTab::Indexer &indexer;
    70   AltList alternatives;
    71   const TypeEnvironment &env;
    72 };
    73 
    74 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env )
    75 ;
    76 
     65    Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
    7766} // namespace ResolvExpr
    7867
    79 #endif /* #ifndef RESOLVEXPR_ALTERNATIVEFINDER_H */
     68#endif // ALTERNATIVEFINDER_H
  • translator/ResolvExpr/AlternativePrinter.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: AlternativePrinter.cc,v 1.5 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    81#include "AlternativePrinter.h"
    92#include "AlternativeFinder.h"
     
    158
    169namespace ResolvExpr {
     10    AlternativePrinter::AlternativePrinter( std::ostream &os ) : SymTab::Indexer( false ), os( os ) {}
    1711
    18 AlternativePrinter::AlternativePrinter( std::ostream &os )
    19   : SymTab::Indexer( false ), os( os )
    20 {
    21 }
    22 
    23 void
    24 AlternativePrinter::visit(ExprStmt *exprStmt)
    25 {
    26   TypeEnvironment env;
    27   AlternativeFinder finder( *this, env );
    28   finder.findWithAdjustment( exprStmt->get_expr() );
    29   int count = 1;
    30   os << "There are " << finder.get_alternatives().size() << " alternatives" << std::endl;
    31   for( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    32     os << "Alternative " << count++ << " ==============" << std::endl;
    33     printAll( i->expr->get_results(), os );
    34 //    i->print( os );
    35     os << std::endl;
    36   }
    37 }
    38 
     12    void AlternativePrinter::visit( ExprStmt *exprStmt ) {
     13        TypeEnvironment env;
     14        AlternativeFinder finder( *this, env );
     15        finder.findWithAdjustment( exprStmt->get_expr() );
     16        int count = 1;
     17        os << "There are " << finder.get_alternatives().size() << " alternatives" << std::endl;
     18        for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     19            os << "Alternative " << count++ << " ==============" << std::endl;
     20            printAll( i->expr->get_results(), os );
     21            //    i->print( os );
     22            os << std::endl;
     23        } // for
     24    } // AlternativePrinter::visit
    3925} // namespace ResolvExpr
  • translator/ResolvExpr/AlternativePrinter.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: AlternativePrinter.h,v 1.2 2005/08/29 20:14:15 rcbilson Exp $
    5  *
    6  */
    7 
    8 #ifndef RESOLVEXPR_ALTERNATIVEPRINTER_H
    9 #define RESOLVEXPR_ALTERNATIVEPRINTER_H
     1#ifndef ALTERNATIVEPRINTER_H
     2#define ALTERNATIVEPRINTER_H
    103
    114#include <iostream>
     
    158
    169namespace ResolvExpr {
    17 
    18 class AlternativePrinter : public SymTab::Indexer
    19 {
    20 public:
    21   AlternativePrinter( std::ostream &os );
    22   virtual void visit(ExprStmt *exprStmt);
    23 
    24 private:
    25   std::ostream &os;
    26 };
    27 
     10    class AlternativePrinter : public SymTab::Indexer {
     11      public:
     12        AlternativePrinter( std::ostream &os );
     13        virtual void visit(ExprStmt *exprStmt);
     14      private:
     15        std::ostream &os;
     16    };
    2817} // namespace ResolvExpr
    2918
    30 #endif /* #ifndef RESOLVEXPR_ALTERNATIVEPRINTER_H */
     19#endif // ALTERNATIVEPRINTER_H
  • translator/ResolvExpr/Cost.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Cost.h,v 1.2 2003/01/27 14:46:59 rcbilson Exp $
    5  *
    6  */
    7 
    81#ifndef RESOLVEXPR_COST_H
    92#define RESOLVEXPR_COST_H
     
    125
    136namespace ResolvExpr {
     7    class Cost {
     8      public:
     9        Cost();
     10        Cost( int unsafe, int poly, int safe );
     11 
     12        void incUnsafe( int inc = 1 );
     13        void incPoly( int inc = 1 );
     14        void incSafe( int inc = 1 );
     15 
     16        Cost operator+( const Cost &other ) const;
     17        Cost operator-( const Cost &other ) const;
     18        Cost &operator+=( const Cost &other );
     19        bool operator<( const Cost &other ) const;
     20        bool operator==( const Cost &other ) const;
     21        bool operator!=( const Cost &other ) const;
     22        friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
     23 
     24        static const Cost zero;
     25        static const Cost infinity;
     26      private:
     27        int compare( const Cost &other ) const;
    1428
    15 class Cost
    16 {
    17 public:
    18   Cost();
    19   Cost( int unsafe, int poly, int safe );
    20  
    21   void incUnsafe( int inc = 1 );
    22   void incPoly( int inc = 1 );
    23   void incSafe( int inc = 1 );
    24  
    25   Cost operator+( const Cost &other ) const;
    26   Cost operator-( const Cost &other ) const;
    27   Cost &operator+=( const Cost &other );
    28   bool operator<( const Cost &other ) const;
    29   bool operator==( const Cost &other ) const;
    30   bool operator!=( const Cost &other ) const;
    31   friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    32  
    33   static const Cost zero;
    34   static const Cost infinity;
    35  
    36 private:
    37   int compare( const Cost &other ) const;
     29        int unsafe;
     30        int poly;
     31        int safe;
     32    };
    3833
    39   int unsafe;
    40   int poly;
    41   int safe;
    42 };
     34    inline Cost::Cost() : unsafe( 0 ), poly( 0 ), safe( 0 ) {}
    4335
    44 inline
    45 Cost::Cost()
    46   : unsafe( 0 ), poly( 0 ), safe( 0 )
    47 {
    48 }
     36    inline Cost::Cost( int unsafe, int poly, int safe ) : unsafe( unsafe ), poly( poly ), safe( safe ) {}
    4937
    50 inline
    51 Cost::Cost( int unsafe, int poly, int safe )
    52   : unsafe( unsafe ), poly( poly ), safe( safe )
    53 {
    54 }
     38    inline void
     39        Cost::incUnsafe( int inc ) {
     40        unsafe += inc;
     41    }
    5542
    56 inline void
    57 Cost::incUnsafe( int inc )
    58 {
    59   unsafe += inc;
    60 }
     43    inline void
     44        Cost::incPoly( int inc ) {
     45        unsafe += inc;
     46    }
    6147
    62 inline void
    63 Cost::incPoly( int inc )
    64 {
    65   unsafe += inc;
    66 }
     48    inline void
     49        Cost::incSafe( int inc ) {
     50        unsafe += inc;
     51    }
    6752
    68 inline void
    69 Cost::incSafe( int inc )
    70 {
    71   unsafe += inc;
    72 }
     53    inline Cost Cost::operator+( const Cost &other ) const {
     54        return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe );
     55    }
    7356
    74 inline Cost
    75 Cost::operator+( const Cost &other ) const
    76 {
    77   return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe );
    78 }
     57    inline Cost Cost::operator-( const Cost &other ) const {
     58        return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe );
     59    }
    7960
    80 inline Cost
    81 Cost::operator-( const Cost &other ) const
    82 {
    83   return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe );
    84 }
     61    inline Cost &Cost::operator+=( const Cost &other ) {
     62        unsafe += other.unsafe;
     63        poly += other.poly;
     64        safe += other.safe;
     65        return *this;
     66    }
    8567
    86 inline Cost &
    87 Cost::operator+=( const Cost &other )
    88 {
    89    unsafe += other.unsafe;
    90    poly += other.poly;
    91    safe += other.safe;
    92    return *this;
    93 }
     68    inline bool Cost::operator<( const Cost &other ) const {
     69            if ( *this == infinity ) return false;
     70            if ( other == infinity ) return true;
     71            if ( unsafe > other.unsafe ) {
     72                return false;
     73            } else if ( unsafe < other.unsafe ) {
     74                return true;
     75            } else if ( poly > other.poly ) {
     76                return false;
     77            } else if ( poly < other.poly ) {
     78                return true;
     79            } else if ( safe > other.safe ) {
     80                return false;
     81            } else if ( safe < other.safe ) {
     82                return true;
     83            } else {
     84                return false;
     85            }
     86        }
    9487
    95 inline bool
    96 Cost::operator<( const Cost &other ) const
    97 {
    98   if( *this == infinity ) return false;
    99   if( other == infinity ) return true;
    100   if( unsafe > other.unsafe ) {
    101     return false;
    102   } else if( unsafe < other.unsafe ) {
    103     return true;
    104   } else if( poly > other.poly ) {
    105     return false;
    106   } else if( poly < other.poly ) {
    107     return true;
    108   } else if( safe > other.safe ) {
    109     return false;
    110   } else if( safe < other.safe ) {
    111     return true;
    112   } else {
    113     return false;
    114   }
    115 }
     88    inline bool Cost::operator==( const Cost &other ) const {
     89        return unsafe == other.unsafe
     90        && poly == other.poly
     91        && safe == other.safe;
     92    }
    11693
    117 inline bool
    118 Cost::operator==( const Cost &other ) const
    119 {
    120   return unsafe == other.unsafe
    121          && poly == other.poly
    122          && safe == other.safe;
    123 }
     94    inline bool Cost::operator!=( const Cost &other ) const {
     95        return !( *this == other );
     96    }
    12497
    125 inline bool
    126 Cost::operator!=( const Cost &other ) const
    127 {
    128   return !( *this == other );
    129 }
    130 
    131 inline std::ostream &
    132 operator<<( std::ostream &os, const Cost &cost )
    133 {
    134   os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe << " )";
    135   return os;
    136 }
    137 
     98    inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
     99        os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe << " )";
     100        return os;
     101    }
    138102} // namespace ResolvExpr
    139103
    140 #endif /* #ifndef RESOLVEXPR_COST_H */
     104#endif // RESOLVEXPR_COST_H
  • translator/ResolvExpr/ResolveTypeof.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: ResolveTypeof.cc,v 1.2 2005/08/29 20:14:16 rcbilson Exp $
    5  *
    6  */
    7 
    81#include "ResolveTypeof.h"
    92#include "Alternative.h"
     
    158
    169namespace ResolvExpr {
     10    namespace {
     11#if 0
     12        void
     13        printAlts( const AltList &list, std::ostream &os, int indent = 0 )
     14        {
     15            for( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
     16                i->print( os, indent );
     17                os << std::endl;
     18            }
     19        }
     20#endif
     21    }
    1722
    18 namespace {
     23    class ResolveTypeof : public Mutator {
     24      public:
     25        ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
     26        Type *mutate( TypeofType *typeofType );
     27
     28      private:
     29        const SymTab::Indexer &indexer;
     30    };
     31
     32    Type *resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
     33        ResolveTypeof mutator( indexer );
     34        return type->acceptMutator( mutator );
     35    }
     36
     37    Type *ResolveTypeof::mutate( TypeofType *typeofType ) {
    1938#if 0
    20   void
    21   printAlts( const AltList &list, std::ostream &os, int indent = 0 )
    22   {
    23     for( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    24       i->print( os, indent );
    25       os << std::endl;
     39        std::cout << "resolving typeof: ";
     40        typeofType->print( std::cout );
     41        std::cout << std::endl;
     42#endif
     43        if ( typeofType->get_expr() ) {
     44            Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
     45            assert( newExpr->get_results().size() > 0 );
     46            Type *newType;
     47            if ( newExpr->get_results().size() > 1 ) {
     48                TupleType *tupleType = new TupleType( Type::Qualifiers() );
     49                cloneAll( newExpr->get_results(), tupleType->get_types() );
     50                newType = tupleType;
     51            } else {
     52                newType = newExpr->get_results().front()->clone();
     53            }
     54            delete typeofType;
     55            return newType;
     56        }
     57        return typeofType;
    2658    }
    27   }
    28 #endif
    29 }
    30 
    31 class ResolveTypeof : public Mutator
    32 {
    33 public:
    34   ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    35   Type *mutate( TypeofType *typeofType );
    36 
    37 private:
    38   const SymTab::Indexer &indexer;
    39 };
    40 
    41 Type *
    42 resolveTypeof( Type *type, const SymTab::Indexer &indexer )
    43 {
    44   ResolveTypeof mutator( indexer );
    45   return type->acceptMutator( mutator );
    46 }
    47 
    48 Type *
    49 ResolveTypeof::mutate( TypeofType *typeofType )
    50 {
    51 ///   std::cout << "resolving typeof: ";
    52 ///   typeofType->print( std::cout );
    53 ///   std::cout << std::endl;
    54   if( typeofType->get_expr() ) {
    55     Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
    56     assert( newExpr->get_results().size() > 0 );
    57     Type *newType;
    58     if( newExpr->get_results().size() > 1 ) {
    59       TupleType *tupleType = new TupleType( Type::Qualifiers() );
    60       cloneAll( newExpr->get_results(), tupleType->get_types() );
    61       newType = tupleType;
    62     } else {
    63       newType = newExpr->get_results().front()->clone();
    64     }
    65     delete typeofType;
    66     return newType;
    67   }
    68   return typeofType;
    69 }
    7059
    7160} // namespace ResolvExpr
  • translator/ResolvExpr/ResolveTypeof.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: ResolveTypeof.h,v 1.2 2005/08/29 20:14:16 rcbilson Exp $
    5  *
    6  */
    7 
    8 #ifndef RESOLVEXPR_RESOLVETYPEOF_H
    9 #define RESOLVEXPR_RESOLVETYPEOF_H
     1#ifndef RESOLVETYPEOF_H
     2#define RESOLVETYPEOF_H
    103
    114#include "SynTree/SynTree.h"
     
    136
    147namespace ResolvExpr {
    15 
    16 Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    17 
     8    Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    189} // namespace ResolvExpr
    1910
    20 #endif /* #ifndef RESOLVEXPR_RESOLVETYPEOF_H */
     11#endif // RESOLVETYPEOF_H
  • translator/ResolvExpr/Resolver.cc

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Resolver.cc,v 1.19 2005/08/29 20:14:16 rcbilson Exp $
    5  *
    6  */
    7 
    81#include "Resolver.h"
    92#include "AlternativeFinder.h"
     
    1811#include "utility.h"
    1912
     13#include <iostream>
     14using namespace std;
     15
    2016namespace ResolvExpr {
    21 
    22 class Resolver : public SymTab::Indexer
    23 {
    24 public:
    25   Resolver() : SymTab::Indexer( false ), switchType( 0 ) {}
    26  
    27   virtual void visit( FunctionDecl *functionDecl );
    28   virtual void visit( ObjectDecl *functionDecl );
    29   virtual void visit( TypeDecl *typeDecl );
    30 
    31   virtual void visit( ExprStmt *exprStmt );
    32   virtual void visit( IfStmt *ifStmt );
    33   virtual void visit( WhileStmt *whileStmt );
    34   virtual void visit( ForStmt *forStmt );
    35   virtual void visit( SwitchStmt *switchStmt );
    36   virtual void visit( ChooseStmt *switchStmt );
    37   virtual void visit( CaseStmt *caseStmt );
    38   virtual void visit( ReturnStmt *returnStmt );
    39 
    40   virtual void visit( SingleInit *singleInit );
    41 
    42 private:
    43   std::list< Type* > functionReturn;
    44   Type* initContext;
    45   Type *switchType;
    46 };
    47 
    48 void
    49 resolve( std::list< Declaration* > translationUnit )
    50 {
    51   Resolver resolver;
    52   acceptAll( translationUnit, resolver );
    53 ///   for( std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    54 ///     (*i)->print( std::cerr );
    55 ///     (*i)->accept( resolver );
    56 ///   }
    57 }
    58 
    59 Expression *
    60 resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer )
    61 {
    62   TypeEnvironment env;
    63   return resolveInVoidContext( expr, indexer, env );
    64 }
    65 
    66 namespace {
    67 
    68   void
    69   finishExpr( Expression *expr, const TypeEnvironment &env )
    70   {
    71     expr->set_env( new TypeSubstitution );
    72     env.makeSubstitution( *expr->get_env() );
    73   }
    74 
    75   Expression*
    76   findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer )
    77   {
    78     global_renamer.reset();
    79     TypeEnvironment env;
    80     Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
    81     finishExpr( newExpr, env );
    82     return newExpr;
    83   }
    84  
    85   Expression*
    86   findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer )
    87   {
    88     TypeEnvironment env;
    89     AlternativeFinder finder( indexer, env );
    90     finder.find( untyped );
    91 ///     if( finder.get_alternatives().size() != 1 ) {
    92 ///       std::cout << "untyped expr is ";
    93 ///       untyped->print( std::cout );
    94 ///       std::cout << std::endl << "alternatives are:";
    95 ///       for( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    96 ///         i->print( std::cout );
    97 ///       }
    98 ///     }
    99     assert( finder.get_alternatives().size() == 1 );
    100     Alternative &choice = finder.get_alternatives().front();
    101     Expression *newExpr = choice.expr->clone();
    102     finishExpr( newExpr, choice.env );
    103     return newExpr;
    104   }
    105 
    106   bool
    107   isIntegralType( Type *type )
    108   {
    109     if( dynamic_cast< EnumInstType* >( type ) ) {
    110       return true;
    111     } else if( BasicType *bt = dynamic_cast< BasicType* >( type ) ) {
    112       return bt->isInteger();
    113     } else {
    114       return true;
    115     }
    116   }
    117  
    118   Expression*
    119   findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer )
    120   {
    121     TypeEnvironment env;
    122     AlternativeFinder finder( indexer, env );
    123     finder.find( untyped );
    124 ///     if( finder.get_alternatives().size() != 1 ) {
    125 ///       std::cout << "untyped expr is ";
    126 ///       untyped->print( std::cout );
    127 ///       std::cout << std::endl << "alternatives are:";
    128 ///       for( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    129 ///         i->print( std::cout );
    130 ///       }
    131 ///     }
    132     Expression *newExpr = 0;
    133     const TypeEnvironment *newEnv = 0;
    134     for( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    135       if( i->expr->get_results().size() == 1 && isIntegralType( i->expr->get_results().front() ) ) {
    136         if( newExpr ) {
    137           throw SemanticError( "Too many interpretations for switch control expression", untyped );
    138         } else {
    139           newExpr = i->expr->clone();
    140           newEnv = &i->env;
    141         }
    142       }
    143     }
    144     if( !newExpr ) {
    145       throw SemanticError( "Too many interpretations for switch control expression", untyped );
    146     }
    147     finishExpr( newExpr, *newEnv );
    148     return newExpr;
    149   }
    150  
    151 }
    152  
    153 void
    154 Resolver::visit( ObjectDecl *objectDecl )
    155 {
    156   Type *new_type = resolveTypeof( objectDecl->get_type(), *this );
    157   objectDecl->set_type( new_type );
    158   initContext = new_type;
    159   SymTab::Indexer::visit( objectDecl );
    160 }
    161  
    162 void
    163 Resolver::visit( TypeDecl *typeDecl )
    164 {
    165   if( typeDecl->get_base() ) {
    166     Type *new_type = resolveTypeof( typeDecl->get_base(), *this );
    167     typeDecl->set_base( new_type );
    168   }
    169   SymTab::Indexer::visit( typeDecl );
    170 }
    171  
    172 void
    173 Resolver::visit( FunctionDecl *functionDecl )
    174 {
    175 ///   std::cout << "resolver visiting functiondecl ";
    176 ///   functionDecl->print( std::cout );
    177 ///   std::cout << std::endl;
    178   Type *new_type = resolveTypeof( functionDecl->get_type(), *this );
    179   functionDecl->set_type( new_type );
    180   std::list< Type* > oldFunctionReturn = functionReturn;
    181   functionReturn.clear();
    182   for( std::list< DeclarationWithType* >::const_iterator i = functionDecl->get_functionType()->get_returnVals().begin(); i != functionDecl->get_functionType()->get_returnVals().end(); ++i ) {
    183     functionReturn.push_back( (*i)->get_type() );
    184   }
    185   SymTab::Indexer::visit( functionDecl );
    186   functionReturn = oldFunctionReturn;
    187 }
    188 
    189 void
    190 Resolver::visit( ExprStmt *exprStmt )
    191 {
    192   if( exprStmt->get_expr() ) {
    193     Expression *newExpr = findVoidExpression( exprStmt->get_expr(), *this );
    194     delete exprStmt->get_expr();
    195     exprStmt->set_expr( newExpr );
    196   }
    197 }
    198 
    199 void
    200 Resolver::visit( IfStmt *ifStmt )
    201 {
    202   Expression *newExpr = findSingleExpression( ifStmt->get_condition(), *this );
    203   delete ifStmt->get_condition();
    204   ifStmt->set_condition( newExpr );
    205   Visitor::visit( ifStmt );
    206 }
    207 
    208 void
    209 Resolver::visit( WhileStmt *whileStmt )
    210 {
    211   Expression *newExpr = findSingleExpression( whileStmt->get_condition(), *this );
    212   delete whileStmt->get_condition();
    213   whileStmt->set_condition( newExpr );
    214   Visitor::visit( whileStmt );
    215 }
    216 
    217 void
    218 Resolver::visit( ForStmt *forStmt )
    219 {
    220   Expression *newExpr;
    221   if( forStmt->get_condition() ) {
    222     newExpr = findSingleExpression( forStmt->get_condition(), *this );
    223     delete forStmt->get_condition();
    224     forStmt->set_condition( newExpr );
    225   }
    226  
    227   if( forStmt->get_increment() ) {
    228     newExpr = findVoidExpression( forStmt->get_increment(), *this );
    229     delete forStmt->get_increment();
    230     forStmt->set_increment( newExpr );
    231   }
    232  
    233   Visitor::visit( forStmt );
    234 }
    235 
    236 template< typename SwitchClass >
    237 void
    238 handleSwitchStmt( SwitchClass *switchStmt, SymTab::Indexer &visitor )
    239 {
    240   Expression *newExpr;
    241   newExpr = findIntegralExpression( switchStmt->get_condition(), visitor );
    242   delete switchStmt->get_condition();
    243   switchStmt->set_condition( newExpr );
    244  
    245   visitor.Visitor::visit( switchStmt );
    246 }
    247 
    248 void
    249 Resolver::visit( SwitchStmt *switchStmt )
    250 {
    251   handleSwitchStmt( switchStmt, *this );
    252 }
    253 
    254 void
    255 Resolver::visit( ChooseStmt *switchStmt )
    256 {
    257   handleSwitchStmt( switchStmt, *this );
    258 }
    259 
    260 void
    261 Resolver::visit( CaseStmt *caseStmt )
    262 {
    263   Visitor::visit( caseStmt );
    264 }
    265 
    266 void
    267 Resolver::visit( ReturnStmt *returnStmt )
    268 {
    269   if( returnStmt->get_expr() ) {
    270     CastExpr *castExpr = new CastExpr( returnStmt->get_expr() );
    271     cloneAll( functionReturn, castExpr->get_results() );
    272     Expression *newExpr = findSingleExpression( castExpr, *this );
    273     delete castExpr;
    274     returnStmt->set_expr( newExpr );
    275   }
    276 }
    277 
    278 void
    279 Resolver::visit( SingleInit *singleInit )
    280 {
    281   if( singleInit->get_value() ) {
    282     CastExpr *castExpr = new CastExpr( singleInit->get_value(), initContext->clone() );
    283     Expression *newExpr = findSingleExpression( castExpr, *this );
    284     delete castExpr;
    285     singleInit->set_value( newExpr );
    286   }
    287   singleInit->get_value()->accept( *this );
    288 }
    289 
     17    class Resolver : public SymTab::Indexer {
     18      public:
     19        Resolver() : SymTab::Indexer( false ), switchType( 0 ) {}
     20 
     21        virtual void visit( FunctionDecl *functionDecl );
     22        virtual void visit( ObjectDecl *functionDecl );
     23        virtual void visit( TypeDecl *typeDecl );
     24
     25        virtual void visit( ExprStmt *exprStmt );
     26        virtual void visit( IfStmt *ifStmt );
     27        virtual void visit( WhileStmt *whileStmt );
     28        virtual void visit( ForStmt *forStmt );
     29        virtual void visit( SwitchStmt *switchStmt );
     30        virtual void visit( ChooseStmt *switchStmt );
     31        virtual void visit( CaseStmt *caseStmt );
     32        virtual void visit( ReturnStmt *returnStmt );
     33
     34        virtual void visit( SingleInit *singleInit );
     35        virtual void visit( ListInit *listInit );
     36      private:
     37        std::list< Type * > functionReturn;
     38        Type *initContext;
     39        Type *switchType;
     40    };
     41
     42    void resolve( std::list< Declaration * > translationUnit ) {
     43        Resolver resolver;
     44        acceptAll( translationUnit, resolver );
     45#if 0
     46        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     47            (*i)->print( std::cerr );
     48            (*i)->accept( resolver );
     49        }
     50#endif
     51    }
     52
     53    Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     54        TypeEnvironment env;
     55        return resolveInVoidContext( expr, indexer, env );
     56    }
     57
     58    namespace {
     59        void finishExpr( Expression *expr, const TypeEnvironment &env ) {
     60            expr->set_env( new TypeSubstitution );
     61            env.makeSubstitution( *expr->get_env() );
     62        }
     63
     64        Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     65            global_renamer.reset();
     66            TypeEnvironment env;
     67            Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
     68            finishExpr( newExpr, env );
     69            return newExpr;
     70        }
     71 
     72        Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     73            TypeEnvironment env;
     74            AlternativeFinder finder( indexer, env );
     75            finder.find( untyped );
     76#if 0
     77            if ( finder.get_alternatives().size() != 1 ) {
     78                std::cout << "untyped expr is ";
     79                untyped->print( std::cout );
     80                std::cout << std::endl << "alternatives are:";
     81                for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     82                    i->print( std::cout );
     83                }
     84            }
     85#endif
     86            assert( finder.get_alternatives().size() == 1 );
     87            Alternative &choice = finder.get_alternatives().front();
     88            Expression *newExpr = choice.expr->clone();
     89            finishExpr( newExpr, choice.env );
     90            return newExpr;
     91        }
     92
     93        bool isIntegralType( Type *type ) {
     94            if ( dynamic_cast< EnumInstType * >( type ) ) {
     95                return true;
     96            } else if ( BasicType *bt = dynamic_cast< BasicType * >( type ) ) {
     97                return bt->isInteger();
     98            } else {
     99                return true;
     100            }
     101        }
     102 
     103        Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     104            TypeEnvironment env;
     105            AlternativeFinder finder( indexer, env );
     106            finder.find( untyped );
     107#if 0
     108            if ( finder.get_alternatives().size() != 1 ) {
     109                std::cout << "untyped expr is ";
     110                untyped->print( std::cout );
     111                std::cout << std::endl << "alternatives are:";
     112                for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     113                    i->print( std::cout );
     114                }
     115            }
     116#endif
     117            Expression *newExpr = 0;
     118            const TypeEnvironment *newEnv = 0;
     119            for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     120                if ( i->expr->get_results().size() == 1 && isIntegralType( i->expr->get_results().front() ) ) {
     121                    if ( newExpr ) {
     122                        throw SemanticError( "Too many interpretations for switch control expression", untyped );
     123                    } else {
     124                        newExpr = i->expr->clone();
     125                        newEnv = &i->env;
     126                    }
     127                }
     128            }
     129            if ( !newExpr ) {
     130                throw SemanticError( "Too many interpretations for switch control expression", untyped );
     131            }
     132            finishExpr( newExpr, *newEnv );
     133            return newExpr;
     134        }
     135 
     136    }
     137 
     138    void Resolver::visit( ObjectDecl *objectDecl ) {
     139        Type *new_type = resolveTypeof( objectDecl->get_type(), *this );
     140        objectDecl->set_type( new_type );
     141        initContext = new_type;
     142        SymTab::Indexer::visit( objectDecl );
     143    }
     144 
     145    void Resolver::visit( TypeDecl *typeDecl ) {
     146        if ( typeDecl->get_base() ) {
     147            Type *new_type = resolveTypeof( typeDecl->get_base(), *this );
     148            typeDecl->set_base( new_type );
     149        }
     150        SymTab::Indexer::visit( typeDecl );
     151    }
     152 
     153    void Resolver::visit( FunctionDecl *functionDecl ) {
     154#if 0
     155        std::cout << "resolver visiting functiondecl ";
     156        functionDecl->print( std::cout );
     157        std::cout << std::endl;
     158#endif
     159        Type *new_type = resolveTypeof( functionDecl->get_type(), *this );
     160        functionDecl->set_type( new_type );
     161        std::list< Type * > oldFunctionReturn = functionReturn;
     162        functionReturn.clear();
     163        for ( std::list< DeclarationWithType * >::const_iterator i = functionDecl->get_functionType()->get_returnVals().begin(); i != functionDecl->get_functionType()->get_returnVals().end(); ++i ) {
     164            functionReturn.push_back( (*i)->get_type() );
     165        }
     166        SymTab::Indexer::visit( functionDecl );
     167        functionReturn = oldFunctionReturn;
     168    }
     169
     170    void Resolver::visit( ExprStmt *exprStmt ) {
     171        if ( exprStmt->get_expr() ) {
     172            Expression *newExpr = findVoidExpression( exprStmt->get_expr(), *this );
     173            delete exprStmt->get_expr();
     174            exprStmt->set_expr( newExpr );
     175        }
     176    }
     177
     178    void Resolver::visit( IfStmt *ifStmt ) {
     179        Expression *newExpr = findSingleExpression( ifStmt->get_condition(), *this );
     180        delete ifStmt->get_condition();
     181        ifStmt->set_condition( newExpr );
     182        Visitor::visit( ifStmt );
     183    }
     184
     185    void Resolver::visit( WhileStmt *whileStmt ) {
     186        Expression *newExpr = findSingleExpression( whileStmt->get_condition(), *this );
     187        delete whileStmt->get_condition();
     188        whileStmt->set_condition( newExpr );
     189        Visitor::visit( whileStmt );
     190    }
     191
     192    void Resolver::visit( ForStmt *forStmt ) {
     193        Expression *newExpr;
     194        if ( forStmt->get_condition() ) {
     195            newExpr = findSingleExpression( forStmt->get_condition(), *this );
     196            delete forStmt->get_condition();
     197            forStmt->set_condition( newExpr );
     198        }
     199 
     200        if ( forStmt->get_increment() ) {
     201            newExpr = findVoidExpression( forStmt->get_increment(), *this );
     202            delete forStmt->get_increment();
     203            forStmt->set_increment( newExpr );
     204        }
     205 
     206        Visitor::visit( forStmt );
     207    }
     208
     209    template< typename SwitchClass >
     210    void handleSwitchStmt( SwitchClass *switchStmt, SymTab::Indexer &visitor ) {
     211        Expression *newExpr;
     212        newExpr = findIntegralExpression( switchStmt->get_condition(), visitor );
     213        delete switchStmt->get_condition();
     214        switchStmt->set_condition( newExpr );
     215 
     216        visitor.Visitor::visit( switchStmt );
     217    }
     218
     219    void Resolver::visit( SwitchStmt *switchStmt ) {
     220        handleSwitchStmt( switchStmt, *this );
     221    }
     222
     223    void Resolver::visit( ChooseStmt *switchStmt ) {
     224        handleSwitchStmt( switchStmt, *this );
     225    }
     226
     227    void Resolver::visit( CaseStmt *caseStmt ) {
     228        Visitor::visit( caseStmt );
     229    }
     230
     231    void Resolver::visit( ReturnStmt *returnStmt ) {
     232        if ( returnStmt->get_expr() ) {
     233            CastExpr *castExpr = new CastExpr( returnStmt->get_expr() );
     234            cloneAll( functionReturn, castExpr->get_results() );
     235            Expression *newExpr = findSingleExpression( castExpr, *this );
     236            delete castExpr;
     237            returnStmt->set_expr( newExpr );
     238        }
     239    }
     240
     241    void Resolver::visit( SingleInit *singleInit ) {
     242        // if ( singleInit->get_value() ) {
     243        //     CastExpr *castExpr = new CastExpr( singleInit->get_value(), initContext->clone() );
     244        //     Expression *newExpr = findSingleExpression( castExpr, *this );
     245        //     delete castExpr;
     246        //     singleInit->set_value( newExpr );
     247        // }
     248        // singleInit->get_value()->accept( *this );
     249    }
     250
     251    void Resolver::visit( ListInit *listInit ) {
     252        // no cast necessary
     253    }
    290254} // namespace ResolvExpr
  • translator/ResolvExpr/Resolver.h

    r3848e0e rd9a0e76  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Resolver.h,v 1.3 2005/08/29 20:14:16 rcbilson Exp $
    5  *
    6  */
    7 
    8 #ifndef RESOLVEXPR_RESOLVER_H
    9 #define RESOLVEXPR_RESOLVER_H
     1#ifndef RESOLVER_H
     2#define RESOLVER_H
    103
    114#include "SynTree/SynTree.h"
     
    136
    147namespace ResolvExpr {
    15 
    16 void resolve( std::list< Declaration* > translationUnit );
    17 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    18 
     8    void resolve( std::list< Declaration * > translationUnit );
     9    Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    1910} // namespace ResolvExpr
    2011
    21 #endif /* #ifndef RESOLVEXPR_RESOLVER_H */
     12#endif // RESOLVER_H
Note: See TracChangeset for help on using the changeset viewer.