Changeset c6b4432 for src/ResolvExpr


Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (23 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode and clean-up.

Location:
src/ResolvExpr
Files:
13 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AdjustExprType.cc

    r790d835 rc6b4432  
    1919#include "AST/Type.hpp"
    2020#include "AST/TypeEnvironment.hpp"
    21 #include "Common/PassVisitor.h"
    22 #include "SymTab/Indexer.h"       // for Indexer
    23 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
    24 #include "SynTree/Mutator.h"      // for Mutator
    25 #include "SynTree/Type.h"         // for PointerType, TypeInstType, Type
    26 #include "TypeEnvironment.h"      // for EqvClass, TypeEnvironment
    2721
    2822namespace ResolvExpr {
    29 
    30 namespace {
    31         class AdjustExprType_old final : public WithShortCircuiting {
    32                 public:
    33                 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    34                 void premutate( VoidType * ) { visit_children = false; }
    35                 void premutate( BasicType * ) { visit_children = false; }
    36                 void premutate( PointerType * ) { visit_children = false; }
    37                 void premutate( ArrayType * ) { visit_children = false; }
    38                 void premutate( FunctionType * ) { visit_children = false; }
    39                 void premutate( StructInstType * ) { visit_children = false; }
    40                 void premutate( UnionInstType * ) { visit_children = false; }
    41                 void premutate( EnumInstType * ) { visit_children = false; }
    42                 void premutate( TraitInstType * ) { visit_children = false; }
    43                 void premutate( TypeInstType * ) { visit_children = false; }
    44                 void premutate( TupleType * ) { visit_children = false; }
    45                 void premutate( VarArgsType * ) { visit_children = false; }
    46                 void premutate( ZeroType * ) { visit_children = false; }
    47                 void premutate( OneType * ) { visit_children = false; }
    48 
    49                 Type * postmutate( ArrayType * arrayType );
    50                 Type * postmutate( FunctionType * functionType );
    51                 Type * postmutate( TypeInstType * aggregateUseType );
    52 
    53                 private:
    54                 const TypeEnvironment & env;
    55                 const SymTab::Indexer & indexer;
    56         };
    57 
    58         AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    59                 : env( env ), indexer( indexer ) {
    60         }
    61 
    62         Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
    63                 PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    64                 arrayType->base = nullptr;
    65                 delete arrayType;
    66                 return pointerType;
    67         }
    68 
    69         Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
    70                 return new PointerType{ Type::Qualifiers(), functionType };
    71         }
    72 
    73         Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
    74                 if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    75                         if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    76                                 return new PointerType{ Type::Qualifiers(), typeInst };
    77                         }
    78                 } else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    79                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) {
    80                                 if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    81                                         return new PointerType{ Type::Qualifiers(), typeInst };
    82                                 } // if
    83                         } // if
    84                 } // if
    85                 return typeInst;
    86         }
    87 } // anonymous namespace
    88 
    89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    90         PassVisitor<AdjustExprType_old> adjuster( env, indexer );
    91         Type * newType = type->acceptMutator( adjuster );
    92         type = newType;
    93 }
    94 
    95 void adjustExprType( Type *& type ) {
    96         TypeEnvironment env;
    97         SymTab::Indexer indexer;
    98         adjustExprType( type, env, indexer );
    99 }
    10023
    10124namespace {
  • src/ResolvExpr/CastCost.cc

    r790d835 rc6b4432  
    2626#include "ResolvExpr/ConversionCost.h"   // for conversionCost
    2727#include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
    28 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
    2928#include "ResolvExpr/typeops.h"          // for ptrsCastable
    3029#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    31 #include "SymTab/Indexer.h"              // for Indexer
    32 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    33 #include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
    3430
    3531#if 0
     
    4036
    4137namespace ResolvExpr {
    42         struct CastCost_old : public ConversionCost {
    43           public:
    44                 CastCost_old( const Type * dest, bool srcIsLvalue,
    45                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    46 
    47                 using ConversionCost::previsit;
    48                 using ConversionCost::postvisit;
    49                 void postvisit( const BasicType * basicType );
    50                 void postvisit( const PointerType * pointerType );
    51         };
    52 
    53         Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
    54                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    55                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    56                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    57                                 if ( eqvClass->type ) {
    58                                         return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    59                                 } else {
    60                                         return Cost::infinity;
    61                                 }
    62                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    63                                 // all typedefs should be gone by this point
    64                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
    65                                 if ( type->base ) {
    66                                         return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
    67                                 } // if
    68                         } // if
    69                 } // if
    70 
    71                 PRINT(
    72                         std::cerr << "castCost ::: src is ";
    73                         src->print( std::cerr );
    74                         std::cerr << std::endl << "dest is ";
    75                         dest->print( std::cerr );
    76                         std::cerr << std::endl << "env is" << std::endl;
    77                         env.print( std::cerr, 8 );
    78                 )
    79 
    80                 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    81                         PRINT( std::cerr << "compatible!" << std::endl; )
    82                         return Cost::zero;
    83                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    84                         return Cost::safe;
    85                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    86                         PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    87                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    88                                 return ptrsCastable( t1, t2, env, indexer );
    89                         });
    90                 } else {
    91                         PassVisitor<CastCost_old> converter(
    92                                 dest, srcIsLvalue, indexer, env,
    93                                 (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
    94                                         castCost );
    95                         src->accept( converter );
    96                         if ( converter.pass.get_cost() == Cost::infinity ) {
    97                                 return Cost::infinity;
    98                         } else {
    99                                 // xxx - why are we adding cost 0 here?
    100                                 return converter.pass.get_cost() + Cost::zero;
    101                         } // if
    102                 } // if
    103         }
    104 
    105         CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
    106                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    107                 : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
    108         }
    109 
    110         void CastCost_old::postvisit( const BasicType * basicType ) {
    111                 const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
    112                 if ( destAsPointer && basicType->isInteger() ) {
    113                         // necessary for, e.g. unsigned long => void *
    114                         cost = Cost::unsafe;
    115                 } else {
    116                         cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
    117                 } // if
    118         }
    119 
    120         void CastCost_old::postvisit( const PointerType * pointerType ) {
    121                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    122                         if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    123                                 cost = Cost::safe;
    124                         } else {
    125                                 TypeEnvironment newEnv( env );
    126                                 newEnv.add( pointerType->forall );
    127                                 newEnv.add( pointerType->base->forall );
    128                                 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
    129                                 if ( castResult > 0 ) {
    130                                         cost = Cost::safe;
    131                                 } else if ( castResult < 0 ) {
    132                                         cost = Cost::infinity;
    133                                 } // if
    134                         } // if
    135                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    136                         if ( destAsBasic->isInteger() ) {
    137                                 // necessary for, e.g. void * => unsigned long
    138                                 cost = Cost::unsafe;
    139                         } // if
    140                 }
    141         }
    14238
    14339namespace {
     
    20096} // anonymous namespace
    20197
    202 
    203 
    20498Cost castCost(
    20599        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
  • src/ResolvExpr/CommonType.cc

    r790d835 rc6b4432  
    2323#include "AST/Pass.hpp"
    2424#include "AST/Type.hpp"
    25 #include "Common/PassVisitor.h"
    26 #include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
    27 #include "SymTab/Indexer.h"              // for Indexer
    28 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl (ptr...
    29 #include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    30 #include "SynTree/Visitor.h"             // for Visitor
    3125#include "Unify.h"                       // for unifyExact, WidenMode
    3226#include "typeops.h"                     // for isFtype
     
    4135
    4236namespace ResolvExpr {
    43         struct CommonType_old : public WithShortCircuiting {
    44                 CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    45                 Type * get_result() const { return result; }
    46 
    47                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    48 
    49                 void postvisit( VoidType * voidType );
    50                 void postvisit( BasicType * basicType );
    51                 void postvisit( PointerType * pointerType );
    52                 void postvisit( ArrayType * arrayType );
    53                 void postvisit( ReferenceType * refType );
    54                 void postvisit( FunctionType * functionType );
    55                 void postvisit( StructInstType * aggregateUseType );
    56                 void postvisit( UnionInstType * aggregateUseType );
    57                 void postvisit( EnumInstType * aggregateUseType );
    58                 void postvisit( TraitInstType * aggregateUseType );
    59                 void postvisit( TypeInstType * aggregateUseType );
    60                 void postvisit( TupleType * tupleType );
    61                 void postvisit( VarArgsType * varArgsType );
    62                 void postvisit( ZeroType * zeroType );
    63                 void postvisit( OneType * oneType );
    64 
    65           private:
    66                 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer );
    67                 template< typename RefType > void handleRefType( RefType * inst, Type * other );
    68 
    69                 Type * result;
    70                 Type * type2;                           // inherited
    71                 bool widenFirst, widenSecond;
    72                 const SymTab::Indexer &indexer;
    73                 TypeEnvironment &env;
    74                 const OpenVarSet &openVars;
    75         };
    76 
    77         Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
    78                 Type * common = nullptr;
    79                 AssertionSet have, need;
    80                 OpenVarSet newOpen( openVars );
    81                 // need unify to bind type variables
    82                 if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
    83                         PRINT(
    84                                 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    85                         )
    86                         if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
    87                                 PRINT(
    88                                         std::cerr << "widen okay" << std::endl;
    89                                 )
    90                                 common->tq |= t1->tq;
    91                                 common->tq |= t2->tq;
    92                                 return common;
    93                         }
    94                 }
    95                 PRINT(
    96                         std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
    97                 )
    98                 return nullptr;
    99         }
    100 
    101         Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    102                 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    103 
    104                 int depth1 = type1->referenceDepth();
    105                 int depth2 = type2->referenceDepth();
    106                 if ( depth1 > 0 || depth2 > 0 ) {
    107                         int diff = depth1-depth2;
    108                         // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
    109                         // if ( diff > 1 || diff < -1 ) return nullptr;
    110 
    111                         // special case where one type has a reference depth of 1 larger than the other
    112                         if ( diff > 0 || diff < 0 ) {
    113                                 PRINT(
    114                                         std::cerr << "reference depth diff: " << diff << std::endl;
    115                                 )
    116                                 Type * result = nullptr;
    117                                 ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
    118                                 ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
    119                                 if ( diff > 0 ) {
    120                                         // deeper on the left
    121                                         assert( ref1 );
    122                                         result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
    123                                 } else {
    124                                         // deeper on the right
    125                                         assert( ref2 );
    126                                         result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
    127                                 }
    128                                 if ( result && ref1 ) {
    129                                         // formal is reference, so result should be reference
    130                                         PRINT(
    131                                                 std::cerr << "formal is reference; result should be reference" << std::endl;
    132                                         )
    133                                         result = new ReferenceType( ref1->tq, result );
    134                                 }
    135                                 PRINT(
    136                                         std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
    137                                 )
    138                                 return result;
    139                         }
    140                         // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
    141                 }
    142 
    143                 type1->accept( visitor );
    144                 Type * result = visitor.pass.get_result();
    145                 if ( ! result ) {
    146                         // this appears to be handling for opaque type declarations
    147                         if ( widenSecond ) {
    148                                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) {
    149                                         if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) {
    150                                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    151                                                 if ( type->get_base() ) {
    152                                                         Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
    153                                                         AssertionSet have, need;
    154                                                         OpenVarSet newOpen( openVars );
    155                                                         type1->tq = Type::Qualifiers();
    156                                                         type->get_base()->tq = tq1;
    157                                                         if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
    158                                                                 result = type1->clone();
    159                                                                 result->tq = tq1 | tq2;
    160                                                         } // if
    161                                                         type1->tq = tq1;
    162                                                         type->get_base()->tq = Type::Qualifiers();
    163                                                 } // if
    164                                         } // if
    165                                 } // if
    166                         } // if
    167                 } // if
    168 #ifdef DEBUG
    169                 std::cerr << "============= commonType" << std::endl << "type1 is ";
    170                 type1->print( std::cerr );
    171                 std::cerr << " type2 is ";
    172                 type2->print( std::cerr );
    173                 if ( result ) {
    174                         std::cerr << " common type is ";
    175                         result->print( std::cerr );
    176                 } else {
    177                         std::cerr << " no common type";
    178                 } // if
    179                 std::cerr << std::endl;
    180 #endif
    181                 return result;
    182         }
    18337
    18438        // GENERATED START, DO NOT EDIT
     
    488342                "Each basic type kind should have a corresponding row in the combined type matrix"
    489343        );
    490 
    491         CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    492                 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    493         }
    494 
    495         void CommonType_old::postvisit( VoidType * ) {}
    496 
    497         void CommonType_old::postvisit( BasicType * basicType ) {
    498                 if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) {
    499                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ (ast::BasicType::Kind)(int)otherBasic->get_kind() ];
    500                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) {
    501                                 result = new BasicType( basicType->tq | otherBasic->tq, newType );
    502                         } // if
    503                 } else if (  dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    504                         // use signed int in lieu of the enum/zero/one type
    505                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    506                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    507                                 result = new BasicType( basicType->tq | type2->tq, newType );
    508                         } // if
    509                 } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
    510                         const EnumDecl* enumDecl = enumInst->baseEnum;
    511                         if ( const Type* baseType = enumDecl->base ) {
    512                                 result = baseType->clone();
    513                         } else {
    514                                 BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    515                                 if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    516                                         result = new BasicType( basicType->tq | type2->tq, newType );
    517                                 } // if
    518                         }
    519                 }
    520         }
    521 
    522         template< typename Pointer >
    523         void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
    524                 if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
    525                         OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
    526                         if ( entry != openVars.end() ) {
    527                                 AssertionSet need, have;
    528                                 WidenMode widen( widenFirst, widenSecond );
    529                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    530                         }
    531                 }
    532                 result = voidPointer->clone();
    533                 result->tq |= otherPointer->tq;
    534         }
    535 
    536         void CommonType_old::postvisit( PointerType * pointerType ) {
    537                 if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
    538                         // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    539                         if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    540                                 getCommonWithVoidPointer( otherPointer, pointerType );
    541                         } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
    542                                 getCommonWithVoidPointer( pointerType, otherPointer );
    543                         } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
    544                                            && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
    545                                 // std::cerr << "middle case" << std::endl;
    546                                 Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq;
    547                                 pointerType->get_base()->tq = Type::Qualifiers();
    548                                 otherPointer->get_base()->tq = Type::Qualifiers();
    549                                 AssertionSet have, need;
    550                                 OpenVarSet newOpen( openVars );
    551                                 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
    552                                         // std::cerr << "unifyExact success" << std::endl;
    553                                         if ( tq1 < tq2 ) {
    554                                                 result = pointerType->clone();
    555                                         } else {
    556                                                 result = otherPointer->clone();
    557                                         } // if
    558                                         strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
    559                                 } else {
    560                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    561                                 } // if
    562                                 pointerType->get_base()->tq = tq1;
    563                                 otherPointer->get_base()->tq = tq2;
    564                         } // if
    565                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    566                         result = pointerType->clone();
    567                         result->tq |= type2->tq;
    568                 } // if
    569         }
    570 
    571         void CommonType_old::postvisit( ArrayType * ) {}
    572 
    573         void CommonType_old::postvisit( ReferenceType * refType ) {
    574                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
    575                         // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
    576                         // std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl;
    577                         if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
    578                                 getCommonWithVoidPointer( otherRef, refType );
    579                         } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
    580                                 getCommonWithVoidPointer( refType, otherRef );
    581                         } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
    582                                            && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
    583                                 // std::cerr << "middle case" << std::endl;
    584                                 Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq;
    585                                 refType->get_base()->tq = Type::Qualifiers();
    586                                 otherRef->get_base()->tq = Type::Qualifiers();
    587                                 AssertionSet have, need;
    588                                 OpenVarSet newOpen( openVars );
    589                                 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
    590                                         if ( tq1 < tq2 ) {
    591                                                 result = refType->clone();
    592                                         } else {
    593                                                 result = otherRef->clone();
    594                                         } // if
    595                                         strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
    596                                 } else {
    597                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    598                                 } // if
    599                                 refType->get_base()->tq = tq1;
    600                                 otherRef->get_base()->tq = tq2;
    601                         } // if
    602                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    603                         result = refType->clone();
    604                         result->tq |= type2->tq;
    605                 } // if
    606         }
    607 
    608         void CommonType_old::postvisit( FunctionType * ) {}
    609         void CommonType_old::postvisit( StructInstType * ) {}
    610         void CommonType_old::postvisit( UnionInstType * ) {}
    611 
    612         void CommonType_old::postvisit( EnumInstType * enumInstType ) {
    613                 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    614                         // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    615                         result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
    616                 } // if
    617         }
    618 
    619         void CommonType_old::postvisit( TraitInstType * ) {
    620         }
    621 
    622         void CommonType_old::postvisit( TypeInstType * inst ) {
    623                 if ( widenFirst ) {
    624                         const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
    625                         if ( nt ) {
    626                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    627                                 if ( type->get_base() ) {
    628                                         Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
    629                                         AssertionSet have, need;
    630                                         OpenVarSet newOpen( openVars );
    631                                         type2->tq = Type::Qualifiers();
    632                                         type->get_base()->tq = tq1;
    633                                         if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
    634                                                 result = type2->clone();
    635                                                 result->tq = tq1 | tq2;
    636                                         } // if
    637                                         type2->tq = tq2;
    638                                         type->get_base()->tq = Type::Qualifiers();
    639                                 } // if
    640                         } // if
    641                 } // if
    642         }
    643 
    644         void CommonType_old::postvisit( TupleType * ) {}
    645         void CommonType_old::postvisit( VarArgsType * ) {}
    646 
    647         void CommonType_old::postvisit( ZeroType * zeroType ) {
    648                 if ( widenFirst ) {
    649                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    650                                 if ( widenSecond || zeroType->tq <= type2->tq ) {
    651                                         result = type2->clone();
    652                                         result->tq |= zeroType->tq;
    653                                 }
    654                         } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {
    655                                 result = new BasicType( zeroType->tq, BasicType::SignedInt );
    656                                 result->tq |= type2->tq;
    657                         }
    658                 }
    659         }
    660 
    661         void CommonType_old::postvisit( OneType * oneType ) {
    662                 if ( widenFirst ) {
    663                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    664                                 if ( widenSecond || oneType->tq <= type2->tq ) {
    665                                         result = type2->clone();
    666                                         result->tq |= oneType->tq;
    667                                 }
    668                         } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    669                                 result = new BasicType( oneType->tq, BasicType::SignedInt );
    670                                 result->tq |= type2->tq;
    671                         }
    672                 }
    673         }
    674344
    675345        class CommonType_new final : public ast::WithShortCircuiting {
  • src/ResolvExpr/CommonType.hpp

    r790d835 rc6b4432  
    1818#include "AST/Fwd.hpp"
    1919#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    20 #include "TypeEnvironment.h"        // for AssertionSet, OpenVarSet
    2120#include "WidenMode.h"              // for WidenMode
    22 
    23 class Type;
    24 namespace SymTab {
    25         class Indexer;
    26 }
    2721
    2822namespace ResolvExpr {
    2923
    30 Type * commonType(
    31         Type * type1, Type * type2, bool widenFirst, bool widenSecond,
    32         const SymTab::Indexer & indexer, TypeEnvironment & env,
    33         const OpenVarSet & openVars );
    3424ast::ptr< ast::Type > commonType(
    3525        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
  • src/ResolvExpr/ConversionCost.cc

    r790d835 rc6b4432  
    2121
    2222#include "ResolvExpr/Cost.h"             // for Cost
    23 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2423#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    2524#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    26 #include "SymTab/Indexer.h"              // for Indexer
    27 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    28 #include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
    29 
    3025
    3126namespace ResolvExpr {
    32 #if 0
    33         const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
    34         const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
    35         const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
    36         const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
    37         const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
    38         const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
    39         const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
    40         const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
    41         const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
    42 #endif
    4327
    4428#if 0
     
    4731#define PRINT(x)
    4832#endif
    49 
    50         Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
    51                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    52                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    53                         PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
    54                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    55                                 if ( eqvClass->type ) {
    56                                         return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    57                                 } else {
    58                                         return Cost::infinity;
    59                                 }
    60                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    61                                 PRINT( std::cerr << " found" << std::endl; )
    62                                 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    63                                 // all typedefs should be gone by this point
    64                                 assert( type );
    65                                 if ( type->base ) {
    66                                         return conversionCost( src, type->base, srcIsLvalue, indexer, env )
    67                                                 + Cost::safe;
    68                                 } // if
    69                         } // if
    70                         PRINT( std::cerr << " not found" << std::endl; )
    71                 } // if
    72                 PRINT(
    73                         std::cerr << "src is ";
    74                         src->print( std::cerr );
    75                         std::cerr << std::endl << "dest is ";
    76                         dest->print( std::cerr );
    77                         std::cerr << std::endl << "env is" << std::endl;
    78                         env.print( std::cerr, 8 );
    79                 )
    80                 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    81                         PRINT( std::cerr << "compatible!" << std::endl; )
    82                         return Cost::zero;
    83                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    84                         return Cost::safe;
    85                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    86                         PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    87                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    88                                 return ptrsAssignable( t1, t2, env );
    89                         });
    90                 } else {
    91                         PassVisitor<ConversionCost> converter(
    92                                 dest, srcIsLvalue, indexer, env,
    93                                 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    94                                         conversionCost );
    95                         src->accept( converter );
    96                         if ( converter.pass.get_cost() == Cost::infinity ) {
    97                                 return Cost::infinity;
    98                         } else {
    99                                 return converter.pass.get_cost() + Cost::zero;
    100                         } // if
    101                 } // if
    102         }
    103 
    104         static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
    105                         int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    106                 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    107                 if ( diff > 0 ) {
    108                         // TODO: document this
    109                         Cost cost = convertToReferenceCost(
    110                                 strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
    111                                 diff-1, indexer, env, func );
    112                         cost.incReference();
    113                         return cost;
    114                 } else if ( diff < -1 ) {
    115                         // TODO: document this
    116                         Cost cost = convertToReferenceCost(
    117                                 src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
    118                                 diff+1, indexer, env, func );
    119                         cost.incReference();
    120                         return cost;
    121                 } else if ( diff == 0 ) {
    122                         const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
    123                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    124                         if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    125                                 PRINT( std::cerr << "converting between references" << std::endl; )
    126                                 Type::Qualifiers tq1 = srcAsRef->base->tq;
    127                                 Type::Qualifiers tq2 = destAsRef->base->tq;
    128                                 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
    129                                         PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    130                                         if ( tq1 == tq2 ) {
    131                                                 // types are the same
    132                                                 return Cost::zero;
    133                                         } else {
    134                                                 // types are the same, except otherPointer has more qualifiers
    135                                                 return Cost::safe;
    136                                         }
    137                                 } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    138                                         int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
    139                                         PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    140                                         if ( assignResult > 0 ) {
    141                                                 return Cost::safe;
    142                                         } else if ( assignResult < 0 ) {
    143                                                 return Cost::unsafe;
    144                                         } // if
    145                                 } // if
    146                         } else {
    147                                 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    148                                 PassVisitor<ConversionCost> converter(
    149                                         dest, srcIsLvalue, indexer, env,
    150                                         (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    151                                                 conversionCost );
    152                                 src->accept( converter );
    153                                 return converter.pass.get_cost();
    154                         } // if
    155                 } else {
    156                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    157                         assert( diff == -1 && destAsRef );
    158                         PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    159                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    160                                 PRINT( std::cerr << "converting compatible base type" << std::endl; )
    161                                 if ( srcIsLvalue ) {
    162                                         PRINT(
    163                                                 std::cerr << "lvalue to reference conversion" << std::endl;
    164                                                 std::cerr << src << " => " << destAsRef << std::endl;
    165                                         )
    166                                         // lvalue-to-reference conversion:  cv lvalue T => cv T &
    167                                         if ( src->tq == destAsRef->base->tq ) {
    168                                                 return Cost::reference; // cost needs to be non-zero to add cast
    169                                         } if ( src->tq < destAsRef->base->tq ) {
    170                                                 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    171                                         } else {
    172                                                 return Cost::unsafe;
    173                                         } // if
    174                                 } else if ( destAsRef->base->get_const() ) {
    175                                         PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    176                                         // rvalue-to-const-reference conversion: T => const T &
    177                                         return Cost::safe;
    178                                 } else {
    179                                         PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
    180                                         // rvalue-to-reference conversion: T => T &
    181                                         return Cost::unsafe;
    182                                 } // if
    183                         } // if
    184                         PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
    185                 }
    186                 return Cost::infinity;
    187         }
    188 
    189         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    190                         const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    191                 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    192                 Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
    193                 PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
    194                 return cost;
    195         }
    196 
    197         ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    198                 : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
    199         }
    20033
    20134        // GENERATED START, DO NOT EDIT
     
    319152        );
    320153
    321         void ConversionCost::postvisit( const VoidType * ) {
    322                 cost = Cost::infinity;
    323         }
    324 
    325         // refactor for code resue
    326         void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
    327                 int tableResult = costMatrix[ src->kind ][ dest->kind ];
    328                 if ( tableResult == -1 ) {
    329                         cost = Cost::unsafe;
    330                 } else {
    331                         cost = Cost::zero;
    332                         cost.incSafe( tableResult );
    333                         cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
    334                 } // if
    335         } // ConversionCost::conversionCostFromBasicToBasic
    336 
    337         void ConversionCost::postvisit(const BasicType * basicType) {
    338                 if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    339                         conversionCostFromBasicToBasic(basicType, destAsBasic);
    340                 } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
    341                         const EnumDecl * base_enum = enumInst->baseEnum;
    342                         if ( const Type * base = base_enum->base ) {
    343                                 if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
    344                                         conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
    345                                 } else {
    346                                         cost = Cost::infinity;
    347                                 } // if
    348                         } else {
    349                                 cost = Cost::unsafe;
    350                         } // if
    351                 } // if
    352                 // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
    353         }
    354 
    355         void ConversionCost::postvisit( const PointerType * pointerType ) {
    356                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    357                         PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    358                         Type::Qualifiers tq1 = pointerType->base->tq;
    359                         Type::Qualifiers tq2 = destAsPtr->base->tq;
    360                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    361                                 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    362                                 if ( tq1 == tq2 ) {
    363                                         // types are the same
    364                                         cost = Cost::zero;
    365                                 } else {
    366                                         // types are the same, except otherPointer has more qualifiers
    367                                         cost = Cost::safe;
    368                                 } // if
    369                         } else {
    370                                 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
    371                                 PRINT( std::cerr << " :: " << assignResult << std::endl; )
    372                                 if ( assignResult > 0 && tq1 <= tq2 ) {
    373                                         // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
    374                                         if ( tq1 == tq2 ) {
    375                                                 cost = Cost::safe;
    376                                         } else if ( tq1 < tq2 ) {
    377                                                 cost = Cost::safe+Cost::safe;
    378                                         }
    379                                 } else if ( assignResult < 0 ) {
    380                                         cost = Cost::unsafe;
    381                                 } // if
    382                                 // assignResult == 0 means Cost::Infinity
    383                         } // if
    384                         // case case for zero_t because it should not be possible to convert pointers to zero_t.
    385                 } // if
    386         }
    387 
    388         void ConversionCost::postvisit( const ArrayType * ) {}
    389 
    390         void ConversionCost::postvisit( const ReferenceType * refType ) {
    391                 // Note: dest can never be a reference, since it would have been caught in an earlier check
    392                 assert( ! dynamic_cast< const ReferenceType * >( dest ) );
    393                 // convert reference to rvalue: cv T1 & => T2
    394                 // recursively compute conversion cost from T1 to T2.
    395                 // cv can be safely dropped because of 'implicit dereference' behavior.
    396                 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
    397                 if ( refType->base->tq == dest->tq ) {
    398                         cost.incReference();  // prefer exact qualifiers
    399                 } else if ( refType->base->tq < dest->tq ) {
    400                         cost.incSafe(); // then gaining qualifiers
    401                 } else {
    402                         cost.incUnsafe(); // lose qualifiers as last resort
    403                 }
    404                 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
    405         }
    406 
    407         void ConversionCost::postvisit( const FunctionType * ) {}
    408 
    409         void ConversionCost::postvisit( const EnumInstType * enumInst) {
    410                 const EnumDecl * enumDecl = enumInst -> baseEnum;
    411                 if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
    412                         cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
    413                 } else {
    414                         static Type::Qualifiers q;
    415                         static BasicType integer( q, BasicType::SignedInt );
    416                         cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
    417                 } // if
    418                 if ( cost < Cost::unsafe ) {
    419                                 cost.incSafe();
    420                 } // if
    421         }
    422 
    423         void ConversionCost::postvisit( const TraitInstType * ) {}
    424 
    425         void ConversionCost::postvisit( const TypeInstType * inst ) {
    426                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    427                         cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
    428                 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    429                         if ( inst->name == destAsInst->name ) {
    430                                 cost = Cost::zero;
    431                         }
    432                 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
    433                         const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    434                         // all typedefs should be gone by this point
    435                         assert( type );
    436                         if ( type->base ) {
    437                                 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
    438                         } // if
    439                 } // if
    440         }
    441 
    442         void ConversionCost::postvisit( const TupleType * tupleType ) {
    443                 Cost c = Cost::zero;
    444                 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
    445                         std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
    446                         std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
    447                         while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
    448                                 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
    449                                 if ( newCost == Cost::infinity ) {
    450                                         return;
    451                                 } // if
    452                                 c += newCost;
    453                         } // while
    454                         if ( destIt != destAsTuple->types.end() ) {
    455                                 cost = Cost::infinity;
    456                         } else {
    457                                 cost = c;
    458                         } // if
    459                 } // if
    460         }
    461 
    462         void ConversionCost::postvisit( const VarArgsType * ) {
    463                 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
    464                         cost = Cost::zero;
    465                 }
    466         }
    467 
    468         void ConversionCost::postvisit( const ZeroType * ) {
    469                 if ( dynamic_cast< const ZeroType * >( dest ) ) {
    470                         cost = Cost::zero;
    471                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    472                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    473                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
    474                         if ( tableResult == -1 ) {
    475                                 cost = Cost::unsafe;
    476                         } else {
    477                                 cost = Cost::zero;
    478                                 cost.incSafe( tableResult + 1 );
    479                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    480                         } // if
    481                 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
    482                         cost = Cost::zero;
    483                         cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
    484                 } // if
    485         }
    486 
    487         void ConversionCost::postvisit( const OneType * ) {
    488                 if ( dynamic_cast< const OneType * >( dest ) ) {
    489                         cost = Cost::zero;
    490                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    491                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    492                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
    493                         if ( tableResult == -1 ) {
    494                                 cost = Cost::unsafe;
    495                         } else {
    496                                 cost = Cost::zero;
    497                                 cost.incSafe( tableResult + 1 );
    498                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    499                         } // if
    500                 } // if
    501         }
    502 
    503154namespace {
    504155        # warning For overload resolution between the two versions.
  • src/ResolvExpr/ConversionCost.h

    r790d835 rc6b4432  
    2222#include "AST/Fwd.hpp"
    2323#include "AST/Pass.hpp"       // for WithShortCircuiting
    24 #include "Common/PassVisitor.h"
    25 #include "SynTree/Visitor.h"  // for Visitor
    26 #include "SynTree/SynTree.h"  // for Visitor Nodes
    2724
    2825namespace SymTab {
     
    3229namespace ResolvExpr {
    3330        class TypeEnvironment;
    34 
    35         Cost conversionCost(
    36                 const Type * src, const Type * dest, bool srcIsLvalue,
    37                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    38 
    39         typedef std::function<Cost(const Type *, const Type *, bool,
    40                 const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
    41 
    42         struct ConversionCost : public WithShortCircuiting {
    43           public:
    44                 ConversionCost( const Type * dest, bool srcIsLvalue,
    45                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    46 
    47                 Cost get_cost() const { return cost; }
    48 
    49                 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    50 
    51                 void postvisit( const VoidType * voidType );
    52                 void postvisit( const BasicType * basicType );
    53                 void postvisit( const PointerType * pointerType );
    54                 void postvisit( const ArrayType * arrayType );
    55                 void postvisit( const ReferenceType * refType );
    56                 void postvisit( const FunctionType * functionType );
    57                 void postvisit( const EnumInstType * aggregateUseType );
    58                 void postvisit( const TraitInstType * aggregateUseType );
    59                 void postvisit( const TypeInstType * aggregateUseType );
    60                 void postvisit( const TupleType * tupleType );
    61                 void postvisit( const VarArgsType * varArgsType );
    62                 void postvisit( const ZeroType * zeroType );
    63                 void postvisit( const OneType * oneType );
    64           protected:
    65                 const Type * dest;
    66                 bool srcIsLvalue;
    67                 const SymTab::Indexer &indexer;
    68                 Cost cost;
    69                 const TypeEnvironment &env;
    70                 CostFunction costFunc;
    71           private:
    72                 // refactor for code resue
    73                 void conversionCostFromBasicToBasic( const BasicType * src, const BasicType* dest );
    74         };
    75 
    76         typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    77         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    78                 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    7931
    8032// Some function pointer types, differ in return type.
  • src/ResolvExpr/CurrentObject.cc

    r790d835 rc6b4432  
    3333#include "Common/utility.h"            // for toString
    3434#include "CurrentObject.h"
    35 #include "SynTree/Constant.h"          // for Constant
    36 #include "SynTree/Declaration.h"       // for ObjectDecl, Declaration, Struc...
    37 #include "SynTree/Expression.h"        // for InitAlternative, VariableExpr
    38 #include "SynTree/Initializer.h"       // for Designation, operator<<
    39 #include "SynTree/Type.h"              // for Type, StructInstType, UnionIns...
    40 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    4135
    4236#if 0
     
    4539#define PRINT(x)
    4640#endif
    47 
    48 namespace ResolvExpr {
    49         template< typename AggrInst >
    50         TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
    51                 assert( inst );
    52                 assert( inst->get_baseParameters() );
    53                 std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
    54                 std::list< Expression * > typeSubs = inst->get_parameters();
    55                 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
    56                 return subs;
    57         }
    58 
    59         TypeSubstitution makeGenericSubstitution( Type * type ) {
    60                 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
    61                         return makeGenericSubstitution( inst );
    62                 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
    63                         return makeGenericSubstitution( inst );
    64                 } else {
    65                         return TypeSubstitution();
    66                 }
    67         }
    68 
    69         class MemberIterator {
    70         public:
    71                 virtual ~MemberIterator() {}
    72 
    73                 /// walks the current object using the given designators as a guide
    74                 virtual void setPosition( std::list< Expression * > & designators ) = 0;
    75 
    76                 /// retrieve the list of possible Type/Designation pairs for the current position in the currect object
    77                 virtual std::list<InitAlternative> operator*() const = 0;
    78 
    79                 /// true if the iterator is not currently at the end
    80                 virtual operator bool() const = 0;
    81 
    82                 /// moves the iterator by one member in the current object
    83                 virtual MemberIterator & bigStep() = 0;
    84 
    85                 /// moves the iterator by one member in the current subobject
    86                 virtual MemberIterator & smallStep() = 0;
    87 
    88                 /// the type of the current object
    89                 virtual Type * getType() = 0;
    90 
    91                 /// the type of the current subobject
    92                 virtual Type * getNext() = 0;
    93 
    94                 /// printing for debug
    95                 virtual void print( std::ostream & out, Indenter indent ) const = 0;
    96 
    97                 /// helper for operator*; aggregates must add designator to each init alternative, but
    98                 /// adding designators in operator* creates duplicates.
    99                 virtual std::list<InitAlternative> first() const = 0; // should be protected
    100         };
    101 
    102         std::ostream & operator<<(std::ostream & out, const MemberIterator & it) {
    103                 Indenter indenter;
    104                 it.print( out, indenter );
    105                 return out;
    106         }
    107 
    108         /// create a new MemberIterator that traverses a type correctly
    109         MemberIterator * createMemberIterator( Type * type );
    110 
    111         /// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry
    112         class SimpleIterator : public MemberIterator {
    113         public:
    114                 SimpleIterator( Type * type ) : type( type ) {}
    115 
    116                 virtual void setPosition( std::list< Expression * > & designators ) {
    117                         assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error
    118                 }
    119 
    120                 virtual std::list<InitAlternative> operator*() const { return first(); }
    121                 virtual operator bool() const { return type; }
    122 
    123                 // big step is the same as small step
    124                 virtual MemberIterator & bigStep() { return smallStep(); }
    125                 virtual MemberIterator & smallStep() {
    126                         type = nullptr;  // type is nullified on increment since SimpleIterators do not have members
    127                         return *this;
    128                 }
    129 
    130                 virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const {
    131                         out << "SimpleIterator(" << type << ")";
    132                 }
    133 
    134                 virtual Type * getType() { return type; }
    135                 virtual Type * getNext() { return type; }
    136 
    137         protected:
    138                 virtual std::list<InitAlternative> first() const {
    139                         if ( type ) return std::list<InitAlternative>{ { type->clone(), new Designation( {} ) } };
    140                         else return std::list<InitAlternative>{};
    141                 }
    142         private:
    143                 Type * type = nullptr;
    144         };
    145 
    146         class ArrayIterator : public MemberIterator {
    147         public:
    148                 ArrayIterator( ArrayType * at ) : array( at ) {
    149                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    150                         base = at->base;
    151                         memberIter = createMemberIterator( base );
    152                         if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
    153                         setSize( at->dimension );
    154                 }
    155 
    156                 ~ArrayIterator() {
    157                         delete memberIter;
    158                 }
    159 
    160         private:
    161                 void setSize( Expression * expr ) {
    162                         auto res = eval( expr );
    163                         if (res.second) {
    164                                 size = res.first;
    165                         } else {
    166                                 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
    167                         }
    168                 }
    169 
    170         public:
    171                 void setPosition( Expression * expr ) {
    172                         // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
    173                         auto arg = eval( expr );
    174                         index = arg.first;
    175                         return;
    176 
    177                         // if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    178                         //      try {
    179                         //              index = constExpr->intValue();
    180                         //      } catch( SemanticErrorException & ) {
    181                         //              SemanticError( expr, "Constant expression of non-integral type in array designator: " );
    182                         //      }
    183                         // } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    184                         //      setPosition( castExpr->get_arg() );
    185                         // } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    186                         //      EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
    187                         //      assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
    188                         //      long long int value;
    189                         //      if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
    190                         //              index = value;
    191                         //      }
    192                         // } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
    193                         //      index = 0; // xxx - get actual sizeof/alignof value?
    194                         // } else {
    195                         //      assertf( false, "4 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    196                         // }
    197                 }
    198 
    199                 virtual void setPosition( std::list< Expression * > & designators ) {
    200                         if ( ! designators.empty() ) {
    201                                 setPosition( designators.front() );
    202                                 designators.pop_front();
    203                                 memberIter->setPosition( designators );
    204                         }
    205                 }
    206 
    207                 virtual std::list<InitAlternative> operator*() const {
    208                         return first();
    209                 }
    210 
    211                 virtual operator bool() const { return index < size; }
    212 
    213                 virtual MemberIterator & bigStep() {
    214                         PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    215                         ++index;
    216                         delete memberIter;
    217                         if ( index < size ) memberIter = createMemberIterator( base );
    218                         else memberIter = nullptr;
    219                         return *this;
    220                 }
    221 
    222                 virtual MemberIterator & smallStep() {
    223                         PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    224                         if ( memberIter ) {
    225                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    226                                 memberIter->smallStep();
    227                                 if ( *memberIter ) {
    228                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    229                                         return *this;
    230                                 }
    231                         }
    232                         return bigStep();
    233                 }
    234 
    235                 virtual Type * getType() { return array; }
    236                 virtual Type * getNext() { return base; }
    237 
    238                 virtual std::list<InitAlternative> first() const {
    239                         PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    240                         if ( memberIter && *memberIter ) {
    241                                 std::list<InitAlternative> ret = memberIter->first();
    242                                 for ( InitAlternative & alt : ret ) {
    243                                         alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) );
    244                                 }
    245                                 return ret;
    246                         }
    247                         return std::list<InitAlternative>();
    248                 }
    249 
    250                 virtual void print( std::ostream & out, Indenter indent ) const {
    251                         out << "ArrayIterator(Array of " << base << ")";
    252                         if ( memberIter ) {
    253                                 Indenter childIndent = indent+1;
    254                                 out << std::endl << childIndent;
    255                                 memberIter->print( out, childIndent );
    256                         }
    257                 }
    258 
    259         private:
    260                 ArrayType * array = nullptr;
    261                 Type * base = nullptr;
    262                 size_t index = 0;
    263                 size_t size = 0;
    264                 MemberIterator * memberIter = nullptr;
    265         };
    266 
    267         class AggregateIterator : public MemberIterator {
    268         public:
    269                 typedef std::list<Declaration *> MemberList;
    270                 typedef MemberList::const_iterator iterator;
    271                 std::string kind = ""; // for debug
    272                 std::string name;
    273                 Type * inst = nullptr;
    274                 const MemberList & members;
    275                 iterator curMember;
    276                 bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning
    277                 Type * curType = nullptr;
    278                 MemberIterator * memberIter = nullptr;
    279                 mutable TypeSubstitution sub;
    280 
    281                 AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
    282                         PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
    283                         init();
    284                 }
    285 
    286                 virtual ~AggregateIterator() {
    287                         delete memberIter;
    288                 }
    289 
    290                 bool init() {
    291                         PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
    292                         if ( curMember != members.end() ) {
    293                                 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) {
    294                                         PRINT( std::cerr << "incremented to field: " << field << std::endl; )
    295                                         curType = field->get_type();
    296                                         memberIter = createMemberIterator( curType );
    297                                         return true;
    298                                 }
    299                         }
    300                         return false;
    301                 }
    302 
    303                 virtual std::list<InitAlternative> operator*() const {
    304                         if (memberIter && *memberIter) {
    305                                 std::list<InitAlternative> ret = memberIter->first();
    306                                 PRINT( std::cerr << "sub: " << sub << std::endl; )
    307                                 for ( InitAlternative & alt : ret ) {
    308                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    309                                         alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
    310                                         // need to substitute for generic types, so that casts are to concrete types
    311                                         PRINT( std::cerr << "  type is: " << alt.type; )
    312                                         sub.apply( alt.type ); // also apply to designation??
    313                                         PRINT( std::cerr << " ==> " << alt.type << std::endl; )
    314                                 }
    315                                 return ret;
    316                         }
    317                         return std::list<InitAlternative>();
    318                 }
    319 
    320                 virtual void setPosition( std::list< Expression * > & designators ) {
    321                         if ( ! designators.empty() ) {
    322                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) {
    323                                         for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
    324                                                 if ( *curMember == varExpr->get_var() ) {
    325                                                         designators.pop_front();
    326                                                         delete memberIter;
    327                                                         memberIter = createMemberIterator( varExpr->get_result() );
    328                                                         curType = varExpr->get_result();
    329                                                         atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin??
    330                                                         memberIter->setPosition( designators );
    331                                                         return;
    332                                                 } // if
    333                                         } // for
    334                                         assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    335                                 } else {
    336                                         assertf( false, "3 bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );
    337                                 } // if
    338                         } // if
    339                 }
    340 
    341                 virtual MemberIterator & smallStep() {
    342                         PRINT( std::cerr << "smallStep in " << kind << std::endl; )
    343                         atbegin = false;
    344                         if ( memberIter ) {
    345                                 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
    346                                 memberIter->smallStep();
    347                                 if ( *memberIter ) {
    348                                         PRINT( std::cerr << "success!" << std::endl; )
    349                                         return *this;
    350                                 }
    351                         }
    352                         return bigStep();
    353                 }
    354 
    355                 virtual Type * getType() { return inst; }
    356                 virtual Type * getNext() {
    357                         if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call???
    358                         return nullptr;
    359                 }
    360 
    361                 virtual std::list<InitAlternative> first() const {
    362                         std::list<InitAlternative> ret;
    363                         PRINT( std::cerr << "first " << kind << std::endl; )
    364                         if ( memberIter && *memberIter ) { // might not need *memberIter??
    365                                 PRINT( std::cerr << "adding children" << std::endl; )
    366                                 ret = memberIter->first();
    367                                 for ( InitAlternative & alt : ret ) {
    368                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    369                                         alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
    370                                 }
    371                         }
    372                         if ( atbegin ) {
    373                                 // xxx - what about case of empty struct??
    374                                 // only add self if at the very beginning of the structure
    375                                 PRINT( std::cerr << "adding self" << std::endl; )
    376                                 ret.push_front( { inst->clone(), new Designation( {} ) } );
    377                         }
    378                         return ret;
    379                 }
    380 
    381                 virtual void print( std::ostream & out, Indenter indent ) const {
    382                         out << kind << "(" << name << ")";
    383                         if ( memberIter ) {
    384                                 Indenter childIndent = indent+1;
    385                                 out << std::endl << childIndent;
    386                                 memberIter->print( out, childIndent );
    387                         }
    388                 }
    389         };
    390 
    391         class UnionIterator : public AggregateIterator {
    392         public:
    393                 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {}
    394 
    395                 virtual operator bool() const { return (memberIter && *memberIter); }
    396                 virtual MemberIterator & bigStep() {
    397                         // unions only initialize one member
    398                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    399                         atbegin = false;
    400                         delete memberIter;
    401                         memberIter = nullptr;
    402                         curType = nullptr;
    403                         curMember = members.end();
    404                         return *this;
    405                 }
    406         };
    407 
    408         class StructIterator : public AggregateIterator {
    409         public:
    410                 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {}
    411 
    412                 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
    413 
    414                 virtual MemberIterator & bigStep() {
    415                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    416                         atbegin = false;
    417                         delete memberIter;
    418                         memberIter = nullptr;
    419                         curType = nullptr;
    420                         for ( ; curMember != members.end(); ) {
    421                                 ++curMember;
    422                                 if ( init() ) {
    423                                         return *this;
    424                                 }
    425                         }
    426                         return *this;
    427                 }
    428         };
    429 
    430         class TupleIterator : public AggregateIterator {
    431         public:
    432                 TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {}
    433 
    434                 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
    435 
    436                 virtual MemberIterator & bigStep() {
    437                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    438                         atbegin = false;
    439                         delete memberIter;
    440                         memberIter = nullptr;
    441                         curType = nullptr;
    442                         for ( ; curMember != members.end(); ) {
    443                                 ++curMember;
    444                                 if ( init() ) {
    445                                         return *this;
    446                                 }
    447                         }
    448                         return *this;
    449                 }
    450         };
    451 
    452         MemberIterator * createMemberIterator( Type * type ) {
    453                 if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) {
    454                         if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) {
    455                                 return new StructIterator( sit );
    456                         } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) {
    457                                 return new UnionIterator( uit );
    458                         } else {
    459                                 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
    460                                 return new SimpleIterator( type );
    461                         }
    462                 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    463                         return new ArrayIterator( at );
    464                 } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
    465                         return new TupleIterator( tt );
    466                 } else {
    467                         return new SimpleIterator( type );
    468                 }
    469         }
    470 
    471         CurrentObject::CurrentObject() {}
    472         CurrentObject::CurrentObject( Type * type ) {
    473                 objStack.push( new SimpleIterator( type ) );
    474         }
    475 
    476 
    477         void CurrentObject::setNext( Designation * designation ) {
    478                 assertf( ! objStack.empty(), "obj stack empty in setNext" );
    479                 PRINT( std::cerr << "____setNext" << designation << std::endl; )
    480                 objStack.top()->setPosition( designation->get_designators() );
    481         }
    482 
    483         Designation * CurrentObject::findNext( Designation * designation ) {
    484                 typedef std::list< Expression * > DesignatorChain;
    485                 PRINT( std::cerr << "___findNext" << std::endl; )
    486                 // find all the d's
    487                 std::list<DesignatorChain> desigAlts{ { } }, newDesigAlts;
    488                 std::list<Type *> curTypes { (objStack.top())->getType() }, newTypes;
    489                 for ( Expression * expr : designation->get_designators() ) {
    490                         PRINT( std::cerr << "____untyped: " << expr << std::endl; )
    491                         std::list<DesignatorChain>::iterator dit = desigAlts.begin();
    492                         if ( NameExpr * nexpr = dynamic_cast<NameExpr *>(expr) ) {
    493                                 for ( Type * t : curTypes ) {
    494                                         assert( dit != desigAlts.end() );
    495                                         DesignatorChain & d = *dit;
    496                                         PRINT( std::cerr << "____actual: " << t << std::endl; )
    497                                         ReferenceToType * refType = dynamic_cast<ReferenceToType *>(t);
    498                                         std::list<Declaration *> members;
    499                                         if ( refType ) {
    500                                                 refType->lookup( nexpr->get_name(), members ); // concatenate identical field name
    501                                                 // xxx - need to also include anonymous members in this somehow...
    502                                                 for ( Declaration * mem: members ) {
    503                                                         if ( ObjectDecl * field = dynamic_cast<ObjectDecl *>(mem) ) {
    504                                                                 PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; )
    505                                                                 DesignatorChain newD = d;
    506                                                                 newD.push_back( new VariableExpr( field ) );
    507                                                                 newDesigAlts.push_back( newD );
    508                                                                 newTypes.push_back( field->get_type() );
    509                                                         } // if
    510                                                 } // for
    511                                         } // if
    512                                         ++dit;
    513                                 } // for
    514                         } else {
    515                                 for ( Type * t : curTypes ) {
    516                                         assert( dit != desigAlts.end() );
    517                                         DesignatorChain & d = *dit;
    518                                         if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) {
    519                                                 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
    520                                                 d.push_back( expr );
    521                                                 newDesigAlts.push_back( d );
    522                                                 newTypes.push_back( at->get_base() );
    523                                         }
    524                                         ++dit;
    525                                 } // for
    526                         } // if
    527                         desigAlts = newDesigAlts;
    528                         newDesigAlts.clear();
    529                         curTypes = newTypes;
    530                         newTypes.clear();
    531                         assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
    532                 } // for
    533                 if ( desigAlts.size() > 1 ) {
    534                         SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
    535                 } else if ( desigAlts.size() == 0 ) {
    536                         SemanticError( designation, "No reasonable alternatives for designation: " );
    537                 }
    538                 DesignatorChain & d = desigAlts.back();
    539                 PRINT( for ( Expression * expr : d ) {
    540                         std::cerr << "____desig: " << expr << std::endl;
    541                 } ) // for
    542                 assertf( ! curTypes.empty(), "empty designator chosen");
    543 
    544                 // set new designators
    545                 assertf( ! objStack.empty(), "empty object stack when setting designation" );
    546                 Designation * actualDesignation = new Designation( d );
    547                 objStack.top()->setPosition( d ); // destroys d
    548                 return actualDesignation;
    549         }
    550 
    551         void CurrentObject::increment() {
    552                 PRINT( std::cerr << "____increment" << std::endl; )
    553                 if ( ! objStack.empty() ) {
    554                         PRINT( std::cerr << *objStack.top() << std::endl; )
    555                         objStack.top()->smallStep();
    556                 }
    557         }
    558 
    559         void CurrentObject::enterListInit() {
    560                 PRINT( std::cerr << "____entering list init" << std::endl; )
    561                 assertf( ! objStack.empty(), "empty obj stack entering list init" );
    562                 Type * type = objStack.top()->getNext();
    563                 if ( type ) {
    564                         objStack.push( createMemberIterator( type ) );
    565                 } else {
    566                         assertf( false, "not sure about this case..." );
    567                 }
    568         }
    569 
    570         void CurrentObject::exitListInit() {
    571                 PRINT( std::cerr << "____exiting list init" << std::endl; )
    572                 assertf( ! objStack.empty(), "objstack empty" );
    573                 delete objStack.top();
    574                 objStack.pop();
    575                 if ( ! objStack.empty() ) {
    576                         PRINT( std::cerr << *objStack.top() << std::endl; )
    577                         objStack.top()->bigStep();
    578                 }
    579         }
    580 
    581         std::list< InitAlternative > CurrentObject::getOptions() {
    582                 PRINT( std::cerr << "____getting current options" << std::endl; )
    583                 assertf( ! objStack.empty(), "objstack empty in getOptions" );
    584                 return **objStack.top();
    585         }
    586 
    587         Type * CurrentObject::getCurrentType() {
    588                 PRINT( std::cerr << "____getting current type" << std::endl; )
    589                 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
    590                 return objStack.top()->getNext();
    591         }
    592 } // namespace ResolvExpr
    59341
    59442namespace ast {
  • src/ResolvExpr/FindOpenVars.cc

    r790d835 rc6b4432  
    1616#include "FindOpenVars.h"
    1717
    18 #include <list>                   // for _List_const_iterator, list<>::const...
    19 #include <map>                    // for map<>::mapped_type
    20 
    2118#include "AST/Pass.hpp"
    2219#include "AST/Type.hpp"
    2320#include "AST/TypeEnvironment.hpp"
    24 #include "Common/PassVisitor.h"
    25 #include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
    26 #include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
    2721
    2822#include <iostream>
    2923
    3024namespace ResolvExpr {
    31         struct FindOpenVars_old : public WithGuards {
    32                 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    33 
    34                 void previsit( const PointerType * pointerType );
    35                 void previsit( const ArrayType * arrayType );
    36                 void previsit( const FunctionType * functionType );
    37                 void previsit( const TupleType * tupleType );
    38 
    39                 void common_action( const Type *type );
    40 
    41                 OpenVarSet &openVars, &closedVars;
    42                 AssertionSet &needAssertions, &haveAssertions;
    43                 bool nextIsOpen;
    44         };
    45 
    46         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    47                 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    48                 type->accept( finder );
    49         }
    50 
    51         FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    52                 : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    53         }
    54 
    55         void FindOpenVars_old::common_action( const Type * type ) {
    56                 if ( nextIsOpen ) {
    57                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    58                                 openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    59                                 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    60                                         needAssertions[ *assert ].isUsed = false;
    61                                 }
    62 ///       cloneAll( (*i)->get_assertions(), needAssertions );
    63 ///       needAssertions.insert( needAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
    64                         }
    65                 } else {
    66                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    67                                 closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    68                                 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    69                                         haveAssertions[ *assert ].isUsed = false;
    70                                 }
    71 ///       cloneAll( (*i)->get_assertions(), haveAssertions );
    72 ///       haveAssertions.insert( haveAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
    73                         } // for
    74                 } // if
    75 ///   std::cerr << "type is ";
    76 ///   type->print( std::cerr );
    77 ///   std::cerr << std::endl << "need is" << std::endl;
    78 ///   printAssertionSet( needAssertions, std::cerr );
    79 ///   std::cerr << std::endl << "have is" << std::endl;
    80 ///   printAssertionSet( haveAssertions, std::cerr );
    81         }
    82 
    83         void FindOpenVars_old::previsit(const PointerType * pointerType) {
    84                 common_action( pointerType );
    85         }
    86 
    87         void FindOpenVars_old::previsit(const ArrayType * arrayType) {
    88                 common_action( arrayType );
    89         }
    90 
    91         void FindOpenVars_old::previsit(const FunctionType * functionType) {
    92                 common_action( functionType );
    93                 nextIsOpen = ! nextIsOpen;
    94                 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
    95         }
    96 
    97         void FindOpenVars_old::previsit(const TupleType * tupleType) {
    98                 common_action( tupleType );
    99         }
    10025
    10126        namespace {
  • src/ResolvExpr/FindOpenVars.h

    r790d835 rc6b4432  
    1717
    1818#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    19 #include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2019
    21 class Type;
    2220namespace ast {
    2321        class Type;
     
    2523
    2624namespace ResolvExpr {
    27         // Updates open and closed variables and their associated assertions
    28         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    29 
    3025        enum FirstMode { FirstClosed, FirstOpen };
    3126
  • src/ResolvExpr/PolyCost.cc

    r790d835 rc6b4432  
    1818#include "AST/Type.hpp"
    1919#include "AST/TypeEnvironment.hpp"
    20 #include "Common/PassVisitor.h"
    21 #include "SymTab/Indexer.h"   // for Indexer
    22 #include "SynTree/Type.h"     // for TypeInstType, Type
    23 #include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2420
    2521namespace ResolvExpr {
    26         struct PolyCost {
    27                 PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer );
    28 
    29                 void previsit( TypeInstType * aggregateUseType );
    30                 int result;
    31                 const TypeEnvironment &tenv;
    32                 const SymTab::Indexer &indexer;
    33         };
    34 
    35         int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
    36                 PassVisitor<PolyCost> coster( env, indexer );
    37                 type->accept( coster );
    38                 return (coster.pass.result > 0) ? 1 : 0;
    39         }
    40 
    41         PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) {
    42         }
    43 
    44         void PolyCost::previsit(TypeInstType * typeInst) {
    45                 if ( const EqvClass *eqvClass = tenv.lookup( typeInst->name ) ) {
    46                         if ( eqvClass->type ) {
    47                                 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass->type ) ) {
    48                                         if ( indexer.lookupType( otherTypeInst->name ) ) {
    49                                                 // bound to opaque type
    50                                                 result += 1;
    51                                         } // if
    52                                 } else {
    53                                         // bound to concrete type
    54                                         result += 1;
    55                                 } // if
    56                         } // if
    57                 } // if
    58         }
    5922
    6023// TODO: When the old PolyCost is torn out get rid of the _new suffix.
  • src/ResolvExpr/PtrsAssignable.cc

    r790d835 rc6b4432  
    1919#include "AST/Type.hpp"
    2020#include "AST/TypeEnvironment.hpp"
    21 #include "Common/PassVisitor.h"
    22 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    23 #include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    24 #include "SynTree/Visitor.h"             // for Visitor
    25 
    2621
    2722namespace ResolvExpr {
    28         struct PtrsAssignable : public WithShortCircuiting {
    29                 PtrsAssignable( const Type * dest, const TypeEnvironment &env );
    30 
    31                 int get_result() const { return result; }
    32 
    33                 void previsit( const Type * ) { visit_children = false; }
    34 
    35                 void postvisit( const VoidType * voidType );
    36                 void postvisit( const BasicType * basicType );
    37                 void postvisit( const PointerType * pointerType );
    38                 void postvisit( const ArrayType * arrayType );
    39                 void postvisit( const FunctionType * functionType );
    40                 void postvisit( const StructInstType * inst );
    41                 void postvisit( const UnionInstType * inst );
    42                 void postvisit( const EnumInstType * inst );
    43                 void postvisit( const TraitInstType * inst );
    44                 void postvisit( const TypeInstType * inst );
    45                 void postvisit( const TupleType * tupleType );
    46                 void postvisit( const VarArgsType * varArgsType );
    47                 void postvisit( const ZeroType * zeroType );
    48                 void postvisit( const OneType * oneType );
    49           private:
    50                 const Type * dest;
    51                 int result;
    52                 const TypeEnvironment &env;
    53         };
    54 
    55         int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
    56                 // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    57                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    58                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    59                                 return ptrsAssignable( src, eqvClass->type, env );
    60                         } // if
    61                 } // if
    62                 if ( dynamic_cast< const VoidType* >( dest ) ) {
    63                         // void * = T * for any T is unsafe
    64                         // xxx - this should be safe, but that currently breaks the build
    65                         return -1;
    66                 } else {
    67                         PassVisitor<PtrsAssignable> ptrs( dest, env );
    68                         src->accept( ptrs );
    69                         return ptrs.pass.get_result();
    70                 } // if
    71         }
    72 
    73         PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    74 
    75         void PtrsAssignable::postvisit( const VoidType * ) {
    76                 // T * = void * is disallowed - this is a change from C, where any
    77                 // void * can be assigned or passed to a non-void pointer without a cast.
    78         }
    79 
    80         void PtrsAssignable::postvisit( const BasicType * ) {}
    81         void PtrsAssignable::postvisit( const PointerType * ) {}
    82         void PtrsAssignable::postvisit( const ArrayType * ) {}
    83         void PtrsAssignable::postvisit( const FunctionType * ) {}
    84 
    85         void PtrsAssignable::postvisit( const StructInstType * ) {}
    86         void PtrsAssignable::postvisit( const UnionInstType * ) {}
    87 
    88         void PtrsAssignable::postvisit( const EnumInstType * ) {
    89                 if ( dynamic_cast< const BasicType* >( dest ) ) {
    90                         // int * = E *, etc. is safe. This isn't technically correct, as each
    91                         // enum has one basic type that it is compatible with, an that type can
    92                         // differ from enum to enum. Without replicating GCC's internal logic,
    93                         // there is no way to know which type this particular enum is compatible
    94                         // with, so punt on this for now.
    95                         result = 1;
    96                 }
    97         }
    98 
    99         void PtrsAssignable::postvisit(  const TraitInstType * ) {}
    100         void PtrsAssignable::postvisit( const TypeInstType * inst ) {
    101                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    102                         if ( eqvClass->type ) {
    103                                 // T * = S * for any S depends on the type bound to T
    104                                 result = ptrsAssignable( eqvClass->type, dest, env );
    105                         }
    106                 } // if
    107         }
    108 
    109         void PtrsAssignable::postvisit( const TupleType * ) {}
    110         void PtrsAssignable::postvisit( const VarArgsType * ) {}
    111         void PtrsAssignable::postvisit( const ZeroType * ) {}
    112         void PtrsAssignable::postvisit( const OneType * ) {}
    11323
    11424// TODO: Get rid of the `_new` suffix when the old version is removed.
  • src/ResolvExpr/PtrsCastable.cc

    r790d835 rc6b4432  
    2020#include "AST/Type.hpp"
    2121#include "AST/TypeEnvironment.hpp"
    22 #include "Common/PassVisitor.h"
    2322#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    24 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    25 #include "SymTab/Indexer.h"              // for Indexer
    26 #include "SynTree/Declaration.h"         // for TypeDecl, TypeDecl::Kind::Ftype
    27 #include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    28 #include "SynTree/Visitor.h"             // for Visitor
    2923
    3024namespace ResolvExpr {
    31         struct PtrsCastable_old : public WithShortCircuiting  {
    32           public:
    33                 PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    34 
    35                 int get_result() const { return result; }
    36 
    37                 void previsit( const Type * ) { visit_children = false; }
    38 
    39                 void postvisit( const VoidType * voidType );
    40                 void postvisit( const BasicType * basicType );
    41                 void postvisit( const PointerType * pointerType );
    42                 void postvisit( const ArrayType * arrayType );
    43                 void postvisit( const FunctionType * functionType );
    44                 void postvisit( const StructInstType * inst );
    45                 void postvisit( const UnionInstType * inst );
    46                 void postvisit( const EnumInstType * inst );
    47                 void postvisit( const TraitInstType * inst );
    48                 void postvisit( const TypeInstType * inst );
    49                 void postvisit( const TupleType * tupleType );
    50                 void postvisit( const VarArgsType * varArgsType );
    51                 void postvisit( const ZeroType * zeroType );
    52                 void postvisit( const OneType * oneType );
    53           private:
    54                 const Type * dest;
    55                 int result;
    56                 const TypeEnvironment &env;
    57                 const SymTab::Indexer &indexer;
    58         };
    59 
    60         namespace {
    61                 int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    62                         if ( dynamic_cast< const FunctionType* >( src ) ) {
    63                                 return -1;
    64                         } else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) {
    65                                 if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) {
    66                                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) {
    67                                                 if ( tyDecl->kind == TypeDecl::Ftype ) {
    68                                                         return -1;
    69                                                 } // if
    70                                         } //if
    71                                 } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    72                                         if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    73                                                 return -1;
    74                                         } // if
    75                                 } // if
    76                         } //if
    77                         return 1;
    78                 }
    79                 int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    80                         return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
    81                 }
    82         }
    83 
    84         int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    85                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    86                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    87                                 // xxx - should this be ptrsCastable?
    88                                 return ptrsAssignable( src, eqvClass->type, env );
    89                         } // if
    90                 } // if
    91                 if ( dynamic_cast< const VoidType* >( dest ) ) {
    92                         return objectCast( src, env, indexer );
    93                 } else {
    94                         PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
    95                         src->accept( ptrs );
    96                         return ptrs.pass.get_result();
    97                 } // if
    98         }
    99 
    100         PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    101                 : dest( dest ), result( 0 ), env( env ), indexer( indexer )     {
    102         }
    103 
    104         void PtrsCastable_old::postvisit( const VoidType * ) {
    105                 result = objectCast( dest, env, indexer );
    106         }
    107 
    108         void PtrsCastable_old::postvisit( const BasicType * ) {
    109                 result = objectCast( dest, env, indexer );
    110         }
    111 
    112         void PtrsCastable_old::postvisit( const PointerType * ) {
    113                 result = objectCast( dest, env, indexer );
    114         }
    115 
    116         void PtrsCastable_old::postvisit( const ArrayType * ) {
    117                 result = objectCast( dest, env, indexer );
    118         }
    119 
    120         void PtrsCastable_old::postvisit( const FunctionType * ) {
    121                 // result = -1;
    122                 result = functionCast( dest, env, indexer );
    123         }
    124 
    125         void PtrsCastable_old::postvisit( const StructInstType * ) {
    126                 result = objectCast( dest, env, indexer );
    127         }
    128 
    129         void PtrsCastable_old::postvisit( const UnionInstType * ) {
    130                 result = objectCast( dest, env, indexer );
    131         }
    132 
    133         void PtrsCastable_old::postvisit( const EnumInstType * ) {
    134                 if ( dynamic_cast< const EnumInstType * >( dest ) ) {
    135                         result = 1;
    136                 } else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
    137                         if ( bt->kind == BasicType::SignedInt ) {
    138                                 result = 0;
    139                         } else {
    140                                 result = 1;
    141                         }
    142                 } else {
    143                         result = objectCast( dest, env, indexer );
    144                 }
    145         }
    146 
    147         void PtrsCastable_old::postvisit( const TraitInstType * ) {}
    148 
    149         void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
    150                 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    151                 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    152         }
    153 
    154         void PtrsCastable_old::postvisit( const TupleType * ) {
    155                 result = objectCast( dest, env, indexer );
    156         }
    157 
    158         void PtrsCastable_old::postvisit( const VarArgsType * ) {
    159                 result = objectCast( dest, env, indexer );
    160         }
    161 
    162         void PtrsCastable_old::postvisit( const ZeroType * ) {
    163                 result = objectCast( dest, env, indexer );
    164         }
    165 
    166         void PtrsCastable_old::postvisit( const OneType * ) {
    167                 result = objectCast( dest, env, indexer );
    168         }
    16925
    17026namespace {
  • src/ResolvExpr/RenameVars.cc

    r790d835 rc6b4432  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/PassVisitor.h"
    2423#include "Common/ScopedMap.h"
    2524#include "Common/SemanticError.h"  // for SemanticError
    2625#include "RenameVars.h"
    27 #include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
    28 #include "SynTree/Expression.h"    // for Expression
    29 #include "SynTree/Type.h"          // for Type, TypeInstType, TraitInstType
    30 #include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3126
    3227#include "AST/Copy.hpp"
     
    4944                }
    5045
    51                 void rename( TypeInstType * type ) {
    52                         auto it = nameMap.find( type->name );
    53                         if ( it != nameMap.end() ) {
    54                                 type->name = it->second;
    55                         }
    56                 }
    57 
    5846                void nextUsage() {
    5947                        ++next_usage_id;
    60                 }
    61 
    62                 void openLevel( Type * type ) {
    63                         if ( ! type->forall.empty() ) {
    64                                 nameMap.beginScope();
    65                                 // renames all "forall" type names to `_${level}_${name}'
    66                                 for ( auto td : type->forall ) {
    67                                         std::ostringstream output;
    68                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    69                                         std::string newname( output.str() );
    70                                         nameMap[ td->get_name() ] = newname;
    71                                         td->name = newname;
    72                                         // ditto for assertion names, the next level in
    73                                         level++;
    74                                 }
    75                         }
    76                 }
    77 
    78                 void closeLevel( Type * type ) {
    79                         if ( !type->forall.empty() ) {
    80                                 nameMap.endScope();
    81                         }
    8248                }
    8349
     
    135101        RenamingData renaming;
    136102
    137         struct RenameVars_old {
    138                 void previsit( TypeInstType * instType ) {
    139                         renaming.openLevel( (Type*)instType );
    140                         renaming.rename( instType );
    141                 }
    142                 void previsit( Type * type ) {
    143                         renaming.openLevel( type );
    144                 }
    145                 void postvisit( Type * type ) {
    146                         renaming.closeLevel( type );
    147                 }
    148         };
    149 
    150103        struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
    151104                RenameMode mode;
     
    178131} // namespace
    179132
    180 void renameTyVars( Type * t ) {
    181         PassVisitor<RenameVars_old> renamer;
    182         t->accept( renamer );
    183 }
    184 
    185133const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
    186134        ast::Pass<RenameVars_new> renamer;
  • src/ResolvExpr/RenameVars.h

    r790d835 rc6b4432  
    1616#pragma once
    1717
    18 #include <list>               // for list
    19 #include <map>                // for map
    20 #include <string>             // for string
    21 
    22 #include "SynTree/SynTree.h"  // for Visitor Nodes
    23 #include "SynTree/Visitor.h"  // for Visitor
    24 
    2518namespace ast {
    2619        class Type;
     
    2821
    2922namespace ResolvExpr {
    30         /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    31         void renameTyVars( Type * );
    32 
    3323        enum RenameMode {
    3424                GEN_USAGE, // for type in VariableExpr
  • src/ResolvExpr/ResolveTypeof.cc

    r790d835 rc6b4432  
    2424#include "AST/Type.hpp"
    2525#include "AST/TypeEnvironment.hpp"
    26 #include "Common/PassVisitor.h"   // for PassVisitor
    2726#include "Common/utility.h"       // for copy
    2827#include "InitTweak/InitTweak.h"  // for isConstExpr
     
    3029#include "Resolver.h"  // for resolveInVoidContext
    3130#include "SymTab/Mangler.h"
    32 #include "SynTree/Expression.h"  // for Expression
    33 #include "SynTree/Mutator.h"     // for Mutator
    34 #include "SynTree/Type.h"        // for TypeofType, Type
    35 
    36 namespace SymTab {
    37 class Indexer;
    38 }  // namespace SymTab
    3931
    4032namespace ResolvExpr {
    41 namespace {
    42 #if 0
    43                 void
    44                 printAlts( const AltList &list, std::ostream &os, int indent = 0 )
    45                 {
    46                         for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    47                                 i->print( os, indent );
    48                                 os << std::endl;
    49                         }
    50                 }
    51 #endif
    52         }
    53 
    54 class ResolveTypeof_old : public WithShortCircuiting {
    55    public:
    56                 ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    57                 void premutate( TypeofType *typeofType );
    58                 Type * postmutate( TypeofType *typeofType );
    59 
    60    private:
    61     const SymTab::Indexer &indexer;
    62 };
    63 
    64         Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    65                 PassVisitor<ResolveTypeof_old> mutator( indexer );
    66                 return type->acceptMutator( mutator );
    67         }
    68 
    69         void ResolveTypeof_old::premutate( TypeofType * ) {
    70                 visit_children = false;
    71         }
    72 
    73     Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
    74 #if 0
    75                 std::cerr << "resolving typeof: ";
    76                 typeofType->print( std::cerr );
    77                 std::cerr << std::endl;
    78 #endif
    79     // pass on null expression
    80                 if ( ! typeofType->expr ) return typeofType;
    81 
    82     bool isBasetypeof = typeofType->is_basetypeof;
    83     auto oldQuals = typeofType->get_qualifiers().val;
    84 
    85     Type* newType;
    86                 if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
    87         // typeof wrapping type
    88         newType = tyExpr->type;
    89         tyExpr->type = nullptr;
    90         delete tyExpr;
    91     } else {
    92         // typeof wrapping expression
    93                         Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
    94                         assert( newExpr->result && ! newExpr->result->isVoid() );
    95         newType = newExpr->result;
    96         newExpr->result = nullptr;
    97         delete typeofType;
    98         delete newExpr;
    99     }
    100 
    101     // clear qualifiers for base, combine with typeoftype quals in any case
    102     if ( isBasetypeof ) {
    103                         // replace basetypeof(<enum>) by int
    104                         if ( dynamic_cast<EnumInstType*>(newType) ) {
    105                                 Type* newerType =
    106                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    107                                         newType->attributes };
    108                                 delete newType;
    109                                 newType = newerType;
    110                         }
    111                         newType->get_qualifiers().val
    112                                 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    113                 } else {
    114         newType->get_qualifiers().val |= oldQuals;
    115     }
    116 
    117     return newType;
    118 }
    11933
    12034namespace {
  • src/ResolvExpr/Resolver.cc

    r790d835 rc6b4432  
    1919#include <vector>                        // for vector
    2020
    21 #include "Alternative.h"                 // for Alternative, AltList
    22 #include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
    2321#include "Candidate.hpp"
    2422#include "CandidateFinder.hpp"
     
    4038#include "Common/Eval.h"                 // for eval
    4139#include "Common/Iterate.hpp"            // for group_iterate
    42 #include "Common/PassVisitor.h"          // for PassVisitor
    4340#include "Common/SemanticError.h"        // for SemanticError
    4441#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4542#include "Common/ToString.hpp"           // for toCString
     43#include "Common/UniqueName.h"           // for UniqueName
    4644#include "InitTweak/GenInit.h"
    4745#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    48 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    49 #include "SymTab/Autogen.h"              // for SizeType
    50 #include "SymTab/Indexer.h"              // for Indexer
    5146#include "SymTab/Mangler.h"              // for Mangler
    52 #include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
    53 #include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
    54 #include "SynTree/Initializer.h"         // for ConstructorInit, SingleInit
    55 #include "SynTree/Statement.h"           // for ForStmt, Statement, BranchStmt
    56 #include "SynTree/Type.h"                // for Type, BasicType, PointerType
    57 #include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
    58 #include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    5947#include "Tuples/Tuples.h"
    6048#include "Validate/FindSpecialDecls.h"   // for SizeType
     
    6351
    6452namespace ResolvExpr {
    65         struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
    66                 Resolver_old() {}
    67                 Resolver_old( const SymTab::Indexer & other ) {
    68                         indexer = other;
    69                 }
    70 
    71                 void previsit( FunctionDecl * functionDecl );
    72                 void postvisit( FunctionDecl * functionDecl );
    73                 void previsit( ObjectDecl * objectDecll );
    74                 void previsit( EnumDecl * enumDecl );
    75                 void previsit( StaticAssertDecl * assertDecl );
    76 
    77                 void previsit( ArrayType * at );
    78                 void previsit( PointerType * at );
    79 
    80                 void previsit( ExprStmt * exprStmt );
    81                 void previsit( AsmExpr * asmExpr );
    82                 void previsit( AsmStmt * asmStmt );
    83                 void previsit( IfStmt * ifStmt );
    84                 void previsit( WhileDoStmt * whileDoStmt );
    85                 void previsit( ForStmt * forStmt );
    86                 void previsit( SwitchStmt * switchStmt );
    87                 void previsit( CaseStmt * caseStmt );
    88                 void previsit( BranchStmt * branchStmt );
    89                 void previsit( ReturnStmt * returnStmt );
    90                 void previsit( ThrowStmt * throwStmt );
    91                 void previsit( CatchStmt * catchStmt );
    92                 void postvisit( CatchStmt * catchStmt );
    93                 void previsit( WaitForStmt * stmt );
    94 
    95                 void previsit( SingleInit * singleInit );
    96                 void previsit( ListInit * listInit );
    97                 void previsit( ConstructorInit * ctorInit );
    98           private:
    99                 typedef std::list< Initializer * >::iterator InitIterator;
    100 
    101                 template< typename PtrType >
    102                 void handlePtrType( PtrType * type );
    103 
    104                 void fallbackInit( ConstructorInit * ctorInit );
    105 
    106                 Type * functionReturn = nullptr;
    107                 CurrentObject currentObject = nullptr;
    108                 bool inEnumDecl = false;
    109         };
    110 
    111         struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
    112                 void previsit( FunctionDecl * );
    113                 void previsit( WithStmt * );
    114 
    115                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    116         };
    117 
    118         void resolve( std::list< Declaration * > translationUnit ) {
    119                 PassVisitor<Resolver_old> resolver;
    120                 acceptAll( translationUnit, resolver );
    121         }
    122 
    123         void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    124                 PassVisitor<Resolver_old> resolver( indexer );
    125                 maybeAccept( decl, resolver );
    126         }
    127 
    128         namespace {
    129                 struct DeleteFinder_old : public WithShortCircuiting    {
    130                         DeletedExpr * delExpr = nullptr;
    131                         void previsit( DeletedExpr * expr ) {
    132                                 if ( delExpr ) visit_children = false;
    133                                 else delExpr = expr;
    134                         }
    135 
    136                         void previsit( Expression * ) {
    137                                 if ( delExpr ) visit_children = false;
    138                         }
    139                 };
    140         }
    141 
    142         DeletedExpr * findDeletedExpr( Expression * expr ) {
    143                 PassVisitor<DeleteFinder_old> finder;
    144                 expr->accept( finder );
    145                 return finder.pass.delExpr;
    146         }
    147 
    148         namespace {
    149                 struct StripCasts_old {
    150                         Expression * postmutate( CastExpr * castExpr ) {
    151                                 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
    152                                         // generated cast is to the same type as its argument, so it's unnecessary -- remove it
    153                                         Expression * expr = castExpr->arg;
    154                                         castExpr->arg = nullptr;
    155                                         std::swap( expr->env, castExpr->env );
    156                                         return expr;
    157                                 }
    158                                 return castExpr;
    159                         }
    160 
    161                         static void strip( Expression *& expr ) {
    162                                 PassVisitor<StripCasts_old> stripper;
    163                                 expr = expr->acceptMutator( stripper );
    164                         }
    165                 };
    166 
    167                 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
    168                         expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    169                         env.makeSubstitution( *expr->env );
    170                         StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
    171                 }
    172 
    173                 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    174                         if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    175                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    176                                         // cast is to the same type as its argument, so it's unnecessary -- remove it
    177                                         expr = castExpr->arg;
    178                                         castExpr->arg = nullptr;
    179                                         std::swap( expr->env, castExpr->env );
    180                                         delete castExpr;
    181                                 }
    182                         }
    183                 }
    184         } // namespace
    185 
    186         namespace {
    187                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    188                         assertf( untyped, "expected a non-null expression." );
    189 
    190                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    191                         static unsigned recursion_level = 0;
    192 
    193                         ++recursion_level;
    194                         TypeEnvironment env;
    195                         AlternativeFinder finder( indexer, env );
    196                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    197                         --recursion_level;
    198 
    199                         #if 0
    200                         if ( finder.get_alternatives().size() != 1 ) {
    201                                 std::cerr << "untyped expr is ";
    202                                 untyped->print( std::cerr );
    203                                 std::cerr << std::endl << "alternatives are:";
    204                                 for ( const Alternative & alt : finder.get_alternatives() ) {
    205                                         alt.print( std::cerr );
    206                                 } // for
    207                         } // if
    208                         #endif
    209 
    210                         // produce filtered list of alternatives
    211                         AltList candidates;
    212                         for ( Alternative & alt : finder.get_alternatives() ) {
    213                                 if ( pred( alt ) ) {
    214                                         candidates.push_back( std::move( alt ) );
    215                                 }
    216                         }
    217 
    218                         // produce invalid error if no candidates
    219                         if ( candidates.empty() ) {
    220                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    221                         }
    222 
    223                         // search for cheapest candidate
    224                         AltList winners;
    225                         bool seen_undeleted = false;
    226                         for ( unsigned i = 0; i < candidates.size(); ++i ) {
    227                                 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
    228 
    229                                 if ( c > 0 ) continue; // skip more expensive than winner
    230 
    231                                 if ( c < 0 ) {
    232                                         // reset on new cheapest
    233                                         seen_undeleted = ! findDeletedExpr( candidates[i].expr );
    234                                         winners.clear();
    235                                 } else /* if ( c == 0 ) */ {
    236                                         if ( findDeletedExpr( candidates[i].expr ) ) {
    237                                                 // skip deleted expression if already seen one equivalent-cost not
    238                                                 if ( seen_undeleted ) continue;
    239                                         } else if ( ! seen_undeleted ) {
    240                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    241                                                 winners.clear();
    242                                                 seen_undeleted = true;
    243                                         }
    244                                 }
    245 
    246                                 winners.emplace_back( std::move( candidates[i] ) );
    247                         }
    248 
    249                         // promote alternative.cvtCost to .cost
    250                         // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
    251                         for ( Alternative& winner : winners ) {
    252                                 winner.cost = winner.cvtCost;
    253                         }
    254 
    255                         // produce ambiguous errors, if applicable
    256                         if ( winners.size() != 1 ) {
    257                                 std::ostringstream stream;
    258                                 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
    259                                 untyped->print( stream );
    260                                 stream << " Alternatives are:\n";
    261                                 printAlts( winners, stream, 1 );
    262                                 SemanticError( untyped->location, stream.str() );
    263                         }
    264 
    265                         // single selected choice
    266                         Alternative& choice = winners.front();
    267 
    268                         // fail on only expression deleted
    269                         if ( ! seen_undeleted ) {
    270                                 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    271                         }
    272 
    273                         // xxx - check for ambiguous expressions
    274 
    275                         // output selected choice
    276                         alt = std::move( choice );
    277                 }
    278 
    279                 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    280                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    281                         if ( ! untyped ) return;
    282                         Alternative choice;
    283                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    284                         finishExpr( choice.expr, choice.env, untyped->env );
    285                         delete untyped;
    286                         untyped = choice.expr;
    287                         choice.expr = nullptr;
    288                 }
    289 
    290                 bool standardAlternativeFilter( const Alternative & ) {
    291                         // currently don't need to filter, under normal circumstances.
    292                         // in the future, this may be useful for removing deleted expressions
    293                         return true;
    294                 }
    295         } // namespace
    296 
    297         // used in resolveTypeof
    298         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
    299                 TypeEnvironment env;
    300                 return resolveInVoidContext( expr, indexer, env );
    301         }
    302 
    303         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
    304                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    305                 // interpretations, an exception has already been thrown.
    306                 assertf( expr, "expected a non-null expression." );
    307 
    308                 CastExpr * untyped = new CastExpr( expr ); // cast to void
    309                 untyped->location = expr->location;
    310 
    311                 // set up and resolve expression cast to void
    312                 Alternative choice;
    313                 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    314                 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    315                 assert( castExpr );
    316                 env = std::move( choice.env );
    317 
    318                 // clean up resolved expression
    319                 Expression * ret = castExpr->arg;
    320                 castExpr->arg = nullptr;
    321 
    322                 // unlink the arg so that it isn't deleted twice at the end of the program
    323                 untyped->arg = nullptr;
    324                 return ret;
    325         }
    326 
    327         void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    328                 resetTyVarRenaming();
    329                 TypeEnvironment env;
    330                 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
    331                 finishExpr( newExpr, env, untyped->env );
    332                 delete untyped;
    333                 untyped = newExpr;
    334         }
    335 
    336         void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    337                 findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    338         }
    339 
    340         void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    341                 assert( untyped && type );
    342                 // transfer location to generated cast for error purposes
    343                 CodeLocation location = untyped->location;
    344                 untyped = new CastExpr( untyped, type );
    345                 untyped->location = location;
    346                 findSingleExpression( untyped, indexer );
    347                 removeExtraneousCast( untyped, indexer );
    348         }
    349 
    350         namespace {
    351                 bool isIntegralType( const Alternative & alt ) {
    352                         Type * type = alt.expr->result;
    353                         if ( dynamic_cast< EnumInstType * >( type ) ) {
    354                                 return true;
    355                         } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
    356                                 return bt->isInteger();
    357                         } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
    358                                 return true;
    359                         } else {
    360                                 return false;
    361                         } // if
    362                 }
    363 
    364                 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    365                         findKindExpression( untyped, indexer, "condition", isIntegralType );
    366                 }
    367         }
    368 
    369 
    370         bool isStructOrUnion( const Alternative & alt ) {
    371                 Type * t = alt.expr->result->stripReferences();
    372                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    373         }
    374 
    375         void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
    376                 PassVisitor<ResolveWithExprs> resolver;
    377                 acceptAll( translationUnit, resolver );
    378         }
    379 
    380         void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
    381                 for ( Expression *& expr : withExprs )  {
    382                         // only struct- and union-typed expressions are viable candidates
    383                         findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    384 
    385                         // if with expression might be impure, create a temporary so that it is evaluated once
    386                         if ( Tuples::maybeImpure( expr ) ) {
    387                                 static UniqueName tmpNamer( "_with_tmp_" );
    388                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    389                                 expr = new VariableExpr( tmp );
    390                                 newStmts.push_back( new DeclStmt( tmp ) );
    391                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    392                                         // generate ctor/dtor and resolve them
    393                                         tmp->init = InitTweak::genCtorInit( tmp );
    394                                         tmp->accept( *visitor );
    395                                 }
    396                         }
    397                 }
    398         }
    399 
    400         void ResolveWithExprs::previsit( WithStmt * withStmt ) {
    401                 resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
    402         }
    403 
    404         void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
    405                 {
    406                         // resolve with-exprs with parameters in scope and add any newly generated declarations to the
    407                         // front of the function body.
    408                         auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
    409                         indexer.addFunctionType( functionDecl->type );
    410                         std::list< Statement * > newStmts;
    411                         resolveWithExprs( functionDecl->withExprs, newStmts );
    412                         if ( functionDecl->statements ) {
    413                                 functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
    414                         } else {
    415                                 assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
    416                         }
    417                 }
    418         }
    419 
    420         void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    421                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    422                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    423                 // The second analysis changes initContext because of a function type can contain object
    424                 // declarations in the return and parameter types. So each value of initContext is
    425                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    426                 GuardValue( currentObject );
    427                 currentObject = CurrentObject( objectDecl->get_type() );
    428                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
    429                         // enumerator initializers should not use the enum type to initialize, since
    430                         // the enum type is still incomplete at this point. Use signed int instead.
    431                         // TODO: BasicType::SignedInt may not longer be true
    432                         currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    433                 }
    434         }
    435 
    436         template< typename PtrType >
    437         void Resolver_old::handlePtrType( PtrType * type ) {
    438                 if ( type->get_dimension() ) {
    439                         findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    440                 }
    441         }
    442 
    443         void Resolver_old::previsit( ArrayType * at ) {
    444                 handlePtrType( at );
    445         }
    446 
    447         void Resolver_old::previsit( PointerType * pt ) {
    448                 handlePtrType( pt );
    449         }
    450 
    451         void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    452 #if 0
    453                 std::cerr << "resolver visiting functiondecl ";
    454                 functionDecl->print( std::cerr );
    455                 std::cerr << std::endl;
    456 #endif
    457                 GuardValue( functionReturn );
    458                 functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    459         }
    460 
    461         void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    462                 // default value expressions have an environment which shouldn't be there and trips up
    463                 // later passes.
    464                 // xxx - it might be necessary to somehow keep the information from this environment, but I
    465                 // can't currently see how it's useful.
    466                 for ( Declaration * d : functionDecl->type->parameters ) {
    467                         if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
    468                                 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
    469                                         delete init->value->env;
    470                                         init->value->env = nullptr;
    471                                 }
    472                         }
    473                 }
    474         }
    475 
    476         void Resolver_old::previsit( EnumDecl * ) {
    477                 // in case we decide to allow nested enums
    478                 GuardValue( inEnumDecl );
    479                 inEnumDecl = true;
    480         }
    481 
    482         void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
    483                 findIntegralExpression( assertDecl->condition, indexer );
    484         }
    485 
    486         void Resolver_old::previsit( ExprStmt * exprStmt ) {
    487                 visit_children = false;
    488                 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
    489                 findVoidExpression( exprStmt->expr, indexer );
    490         }
    491 
    492         void Resolver_old::previsit( AsmExpr * asmExpr ) {
    493                 visit_children = false;
    494                 findVoidExpression( asmExpr->operand, indexer );
    495         }
    496 
    497         void Resolver_old::previsit( AsmStmt * asmStmt ) {
    498                 visit_children = false;
    499                 acceptAll( asmStmt->get_input(), *visitor );
    500                 acceptAll( asmStmt->get_output(), *visitor );
    501         }
    502 
    503         void Resolver_old::previsit( IfStmt * ifStmt ) {
    504                 findIntegralExpression( ifStmt->condition, indexer );
    505         }
    506 
    507         void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
    508                 findIntegralExpression( whileDoStmt->condition, indexer );
    509         }
    510 
    511         void Resolver_old::previsit( ForStmt * forStmt ) {
    512                 if ( forStmt->condition ) {
    513                         findIntegralExpression( forStmt->condition, indexer );
    514                 } // if
    515 
    516                 if ( forStmt->increment ) {
    517                         findVoidExpression( forStmt->increment, indexer );
    518                 } // if
    519         }
    520 
    521         void Resolver_old::previsit( SwitchStmt * switchStmt ) {
    522                 GuardValue( currentObject );
    523                 findIntegralExpression( switchStmt->condition, indexer );
    524 
    525                 currentObject = CurrentObject( switchStmt->condition->result );
    526         }
    527 
    528         void Resolver_old::previsit( CaseStmt * caseStmt ) {
    529                 if ( caseStmt->condition ) {
    530                         std::list< InitAlternative > initAlts = currentObject.getOptions();
    531                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
    532                         // must remove cast from case statement because RangeExpr cannot be cast.
    533                         Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
    534                         findSingleExpression( newExpr, indexer );
    535                         // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
    536                         // Ideally we would perform the conversion internally here.
    537                         if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
    538                                 newExpr = castExpr->arg;
    539                                 castExpr->arg = nullptr;
    540                                 std::swap( newExpr->env, castExpr->env );
    541                                 delete castExpr;
    542                         }
    543                         caseStmt->condition = newExpr;
    544                 }
    545         }
    546 
    547         void Resolver_old::previsit( BranchStmt * branchStmt ) {
    548                 visit_children = false;
    549                 // must resolve the argument for a computed goto
    550                 if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
    551                         if ( branchStmt->computedTarget ) {
    552                                 // computed goto argument is void *
    553                                 findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
    554                         } // if
    555                 } // if
    556         }
    557 
    558         void Resolver_old::previsit( ReturnStmt * returnStmt ) {
    559                 visit_children = false;
    560                 if ( returnStmt->expr ) {
    561                         findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
    562                 } // if
    563         }
    564 
    565         void Resolver_old::previsit( ThrowStmt * throwStmt ) {
    566                 visit_children = false;
    567                 // TODO: Replace *exception type with &exception type.
    568                 if ( throwStmt->get_expr() ) {
    569                         const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
    570                         assert( exception_decl );
    571                         Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
    572                         findSingleExpression( throwStmt->expr, exceptType, indexer );
    573                 }
    574         }
    575 
    576         void Resolver_old::previsit( CatchStmt * catchStmt ) {
    577                 // Until we are very sure this invarent (ifs that move between passes have then)
    578                 // holds, check it. This allows a check for when to decode the mangling.
    579                 if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
    580                         assert( ifStmt->then );
    581                 }
    582                 // Encode the catchStmt so the condition can see the declaration.
    583                 if ( catchStmt->cond ) {
    584                         IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
    585                         catchStmt->cond = nullptr;
    586                         catchStmt->body = ifStmt;
    587                 }
    588         }
    589 
    590         void Resolver_old::postvisit( CatchStmt * catchStmt ) {
    591                 // Decode the catchStmt so everything is stored properly.
    592                 IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
    593                 if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
    594                         assert( ifStmt->condition );
    595                         assert( ifStmt->else_ );
    596                         catchStmt->cond = ifStmt->condition;
    597                         catchStmt->body = ifStmt->else_;
    598                         ifStmt->condition = nullptr;
    599                         ifStmt->else_ = nullptr;
    600                         delete ifStmt;
    601                 }
    602         }
    603 
    60453        template< typename iterator_t >
    60554        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     
    61059                return it != end;
    61160        }
    612 
    613         void Resolver_old::previsit( WaitForStmt * stmt ) {
    614                 visit_children = false;
    615 
    616                 // Resolve all clauses first
    617                 for( auto& clause : stmt->clauses ) {
    618 
    619                         TypeEnvironment env;
    620                         AlternativeFinder funcFinder( indexer, env );
    621 
    622                         // Find all alternatives for a function in canonical form
    623                         funcFinder.findWithAdjustment( clause.target.function );
    624 
    625                         if ( funcFinder.get_alternatives().empty() ) {
    626                                 stringstream ss;
    627                                 ss << "Use of undeclared indentifier '";
    628                                 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    629                                 ss << "' in call to waitfor";
    630                                 SemanticError( stmt->location, ss.str() );
    631                         }
    632 
    633                         if(clause.target.arguments.empty()) {
    634                                 SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
    635                         }
    636 
    637                         // Find all alternatives for all arguments in canonical form
    638                         std::vector< AlternativeFinder > argAlternatives;
    639                         funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
    640 
    641                         // List all combinations of arguments
    642                         std::vector< AltList > possibilities;
    643                         combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    644 
    645                         AltList                func_candidates;
    646                         std::vector< AltList > args_candidates;
    647 
    648                         // For every possible function :
    649                         //      try matching the arguments to the parameters
    650                         //      not the other way around because we have more arguments than parameters
    651                         SemanticErrorException errors;
    652                         for ( Alternative & func : funcFinder.get_alternatives() ) {
    653                                 try {
    654                                         PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    655                                         if( !pointer ) {
    656                                                 SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
    657                                         }
    658 
    659                                         FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    660                                         if( !function ) {
    661                                                 SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
    662                                         }
    663 
    664 
    665                                         {
    666                                                 auto param     = function->parameters.begin();
    667                                                 auto param_end = function->parameters.end();
    668 
    669                                                 if( !advance_to_mutex( param, param_end ) ) {
    670                                                         SemanticError(function, "candidate function not viable: no mutex parameters\n");
    671                                                 }
    672                                         }
    673 
    674                                         Alternative newFunc( func );
    675                                         // Strip reference from function
    676                                         referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    677 
    678                                         // For all the set of arguments we have try to match it with the parameter of the current function alternative
    679                                         for ( auto & argsList : possibilities ) {
    680 
    681                                                 try {
    682                                                         // Declare data structures need for resolution
    683                                                         OpenVarSet openVars;
    684                                                         AssertionSet resultNeed, resultHave;
    685                                                         TypeEnvironment resultEnv( func.env );
    686                                                         makeUnifiableVars( function, openVars, resultNeed );
    687                                                         // add all type variables as open variables now so that those not used in the parameter
    688                                                         // list are still considered open.
    689                                                         resultEnv.add( function->forall );
    690 
    691                                                         // Load type variables from arguemnts into one shared space
    692                                                         simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
    693 
    694                                                         // Make sure we don't widen any existing bindings
    695                                                         resultEnv.forbidWidening();
    696 
    697                                                         // Find any unbound type variables
    698                                                         resultEnv.extractOpenVars( openVars );
    699 
    700                                                         auto param     = function->parameters.begin();
    701                                                         auto param_end = function->parameters.end();
    702 
    703                                                         int n_mutex_param = 0;
    704 
    705                                                         // For every arguments of its set, check if it matches one of the parameter
    706                                                         // The order is important
    707                                                         for( auto & arg : argsList ) {
    708 
    709                                                                 // Ignore non-mutex arguments
    710                                                                 if( !advance_to_mutex( param, param_end ) ) {
    711                                                                         // We ran out of parameters but still have arguments
    712                                                                         // this function doesn't match
    713                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
    714                                                                 }
    715 
    716                                                                 n_mutex_param++;
    717 
    718                                                                 // Check if the argument matches the parameter type in the current scope
    719                                                                 if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    720                                                                         // Type doesn't match
    721                                                                         stringstream ss;
    722                                                                         ss << "candidate function not viable: no known convertion from '";
    723                                                                         (*param)->get_type()->print( ss );
    724                                                                         ss << "' to '";
    725                                                                         arg.expr->get_result()->print( ss );
    726                                                                         ss << "' with env '";
    727                                                                         resultEnv.print(ss);
    728                                                                         ss << "'\n";
    729                                                                         SemanticError( function, ss.str() );
    730                                                                 }
    731 
    732                                                                 param++;
    733                                                         }
    734 
    735                                                         // All arguments match !
    736 
    737                                                         // Check if parameters are missing
    738                                                         if( advance_to_mutex( param, param_end ) ) {
    739                                                                 do {
    740                                                                         n_mutex_param++;
    741                                                                         param++;
    742                                                                 } while( advance_to_mutex( param, param_end ) );
    743 
    744                                                                 // We ran out of arguments but still have parameters left
    745                                                                 // this function doesn't match
    746                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
    747                                                         }
    748 
    749                                                         // All parameters match !
    750 
    751                                                         // Finish the expressions to tie in the proper environments
    752                                                         finishExpr( newFunc.expr, resultEnv );
    753                                                         for( Alternative & alt : argsList ) {
    754                                                                 finishExpr( alt.expr, resultEnv );
    755                                                         }
    756 
    757                                                         // This is a match store it and save it for later
    758                                                         func_candidates.push_back( newFunc );
    759                                                         args_candidates.push_back( argsList );
    760 
    761                                                 }
    762                                                 catch( SemanticErrorException & e ) {
    763                                                         errors.append( e );
    764                                                 }
    765                                         }
    766                                 }
    767                                 catch( SemanticErrorException & e ) {
    768                                         errors.append( e );
    769                                 }
    770                         }
    771 
    772                         // Make sure we got the right number of arguments
    773                         if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    774                         if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    775                         if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    776                         if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    777                         // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    778 
    779                         // Swap the results from the alternative with the unresolved values.
    780                         // Alternatives will handle deletion on destruction
    781                         std::swap( clause.target.function, func_candidates.front().expr );
    782                         for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
    783                                 std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
    784                         }
    785 
    786                         // Resolve the conditions as if it were an IfStmt
    787                         // Resolve the statments normally
    788                         findSingleExpression( clause.condition, this->indexer );
    789                         clause.statement->accept( *visitor );
    790                 }
    791 
    792 
    793                 if( stmt->timeout.statement ) {
    794                         // Resolve the timeout as an size_t for now
    795                         // Resolve the conditions as if it were an IfStmt
    796                         // Resolve the statments normally
    797                         findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
    798                         findSingleExpression( stmt->timeout.condition, this->indexer );
    799                         stmt->timeout.statement->accept( *visitor );
    800                 }
    801 
    802                 if( stmt->orelse.statement ) {
    803                         // Resolve the conditions as if it were an IfStmt
    804                         // Resolve the statments normally
    805                         findSingleExpression( stmt->orelse.condition, this->indexer );
    806                         stmt->orelse.statement->accept( *visitor );
    807                 }
    808         }
    809 
    810         bool isCharType( Type * t ) {
    811                 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
    812                         return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
    813                                 bt->get_kind() == BasicType::UnsignedChar;
    814                 }
    815                 return false;
    816         }
    817 
    818         void Resolver_old::previsit( SingleInit * singleInit ) {
    819                 visit_children = false;
    820                 // resolve initialization using the possibilities as determined by the currentObject cursor
    821                 Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
    822                 findSingleExpression( newExpr, indexer );
    823                 InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
    824 
    825                 // move cursor to the object that is actually initialized
    826                 currentObject.setNext( initExpr->get_designation() );
    827 
    828                 // discard InitExpr wrapper and retain relevant pieces
    829                 newExpr = initExpr->expr;
    830                 initExpr->expr = nullptr;
    831                 std::swap( initExpr->env, newExpr->env );
    832                 // InitExpr may have inferParams in the case where the expression specializes a function
    833                 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
    834                 // sufficient.
    835                 newExpr->spliceInferParams( initExpr );
    836                 delete initExpr;
    837 
    838                 // get the actual object's type (may not exactly match what comes back from the resolver
    839                 // due to conversions)
    840                 Type * initContext = currentObject.getCurrentType();
    841 
    842                 removeExtraneousCast( newExpr, indexer );
    843 
    844                 // check if actual object's type is char[]
    845                 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
    846                         if ( isCharType( at->get_base() ) ) {
    847                                 // check if the resolved type is char *
    848                                 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    849                                         if ( isCharType( pt->get_base() ) ) {
    850                                                 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    851                                                         // strip cast if we're initializing a char[] with a char *,
    852                                                         // e.g.  char x[] = "hello";
    853                                                         newExpr = ce->get_arg();
    854                                                         ce->set_arg( nullptr );
    855                                                         std::swap( ce->env, newExpr->env );
    856                                                         delete ce;
    857                                                 }
    858                                         }
    859                                 }
    860                         }
    861                 }
    862 
    863                 // set initializer expr to resolved express
    864                 singleInit->value = newExpr;
    865 
    866                 // move cursor to next object in preparation for next initializer
    867                 currentObject.increment();
    868         }
    869 
    870         void Resolver_old::previsit( ListInit * listInit ) {
    871                 visit_children = false;
    872                 // move cursor into brace-enclosed initializer-list
    873                 currentObject.enterListInit();
    874                 // xxx - fix this so that the list isn't copied, iterator should be used to change current
    875                 // element
    876                 std::list<Designation *> newDesignations;
    877                 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    878                         // iterate designations and initializers in pairs, moving the cursor to the current
    879                         // designated object and resolving the initializer against that object.
    880                         Designation * des = std::get<0>(p);
    881                         Initializer * init = std::get<1>(p);
    882                         newDesignations.push_back( currentObject.findNext( des ) );
    883                         init->accept( *visitor );
    884                 }
    885                 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list
    886                 listInit->get_designations() = newDesignations; // xxx - memory management
    887                 currentObject.exitListInit();
    888 
    889                 // xxx - this part has not be folded into CurrentObject yet
    890                 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
    891                 //      Type * base = tt->get_baseType()->get_base();
    892                 //      if ( base ) {
    893                 //              // know the implementation type, so try using that as the initContext
    894                 //              ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
    895                 //              currentObject = &tmpObj;
    896                 //              visit( listInit );
    897                 //      } else {
    898                 //              // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
    899                 //              Parent::visit( listInit );
    900                 //      }
    901                 // } else {
    902         }
    903 
    904         // ConstructorInit - fall back on C-style initializer
    905         void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
    906                 // could not find valid constructor, or found an intrinsic constructor
    907                 // fall back on C-style initializer
    908                 delete ctorInit->get_ctor();
    909                 ctorInit->set_ctor( nullptr );
    910                 delete ctorInit->get_dtor();
    911                 ctorInit->set_dtor( nullptr );
    912                 maybeAccept( ctorInit->get_init(), *visitor );
    913         }
    914 
    915         // needs to be callable from outside the resolver, so this is a standalone function
    916         void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    917                 assert( ctorInit );
    918                 PassVisitor<Resolver_old> resolver( indexer );
    919                 ctorInit->accept( resolver );
    920         }
    921 
    922         void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    923                 assert( stmtExpr );
    924                 PassVisitor<Resolver_old> resolver( indexer );
    925                 stmtExpr->accept( resolver );
    926                 stmtExpr->computeResult();
    927                 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
    928         }
    929 
    930         void Resolver_old::previsit( ConstructorInit * ctorInit ) {
    931                 visit_children = false;
    932                 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
    933                 maybeAccept( ctorInit->ctor, *visitor );
    934                 maybeAccept( ctorInit->dtor, *visitor );
    935 
    936                 // found a constructor - can get rid of C-style initializer
    937                 delete ctorInit->init;
    938                 ctorInit->init = nullptr;
    939 
    940                 // intrinsic single parameter constructors and destructors do nothing. Since this was
    941                 // implicitly generated, there's no way for it to have side effects, so get rid of it
    942                 // to clean up generated code.
    943                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
    944                         delete ctorInit->ctor;
    945                         ctorInit->ctor = nullptr;
    946                 }
    947 
    948                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
    949                         delete ctorInit->dtor;
    950                         ctorInit->dtor = nullptr;
    951                 }
    952 
    953                 // xxx - todo -- what about arrays?
    954                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    955                 //      // can reduce the constructor down to a SingleInit using the
    956                 //      // second argument from the ctor call, since
    957                 //      delete ctorInit->get_ctor();
    958                 //      ctorInit->set_ctor( nullptr );
    959 
    960                 //      Expression * arg =
    961                 //      ctorInit->set_init( new SingleInit( arg ) );
    962                 // }
    963         }
    964 
    965         ///////////////////////////////////////////////////////////////////////////
    966         //
    967         // *** NEW RESOLVER ***
    968         //
    969         ///////////////////////////////////////////////////////////////////////////
    97061
    97162        namespace {
  • src/ResolvExpr/SatisfyAssertions.cpp

    r790d835 rc6b4432  
    4646#include "SymTab/Mangler.h"
    4747
    48 
    49 
    5048namespace ResolvExpr {
    5149
  • src/ResolvExpr/SpecCost.cc

    r790d835 rc6b4432  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/PassVisitor.h"
    24 #include "SynTree/Declaration.h"
    25 #include "SynTree/Expression.h"
    26 #include "SynTree/Type.h"
    2723
    2824namespace ResolvExpr {
    29 
    30         /// Counts specializations in a type
    31         class CountSpecs : public WithShortCircuiting, public WithVisitorRef<CountSpecs> {
    32                 int count = -1;  ///< specialization count (-1 for none)
    33 
    34         public:
    35                 int get_count() const { return count >= 0 ? count : 0; }
    36 
    37                 // mark specialization of base type
    38                 void postvisit(PointerType*) { if ( count >= 0 ) ++count; }
    39 
    40                 // mark specialization of base type
    41                 void postvisit(ArrayType*) { if ( count >= 0 ) ++count; }
    42 
    43                 // mark specialization of base type
    44                 void postvisit(ReferenceType*) { if ( count >= 0 ) ++count; }
    45 
    46                 void postvisit(StructInstType*) { if ( count >= 0 ) ++count; }
    47                 void postvisit(UnionInstType*) { if ( count >= 0 ) ++count; }
    48 
    49         private:
    50                 // takes minimum non-negative count over parameter/return list
    51                 void takeminover( int& mincount, std::list<DeclarationWithType*>& dwts ) {
    52                         for ( DeclarationWithType* dwt : dwts ) {
    53                                 count = -1;
    54                                 maybeAccept( dwt->get_type(), *visitor );
    55                                 if ( count != -1 && count < mincount ) mincount = count;
    56                         }
    57                 }
    58 
    59         public:
    60                 // take minimal specialization value over ->returnVals and ->parameters
    61                 void previsit(FunctionType* fty) {
    62                         int mincount = std::numeric_limits<int>::max();
    63                         takeminover( mincount, fty->parameters );
    64                         takeminover( mincount, fty->returnVals );
    65                         // add another level to mincount if set
    66                         count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    67                         // already visited children
    68                         visit_children = false;
    69                 }
    70 
    71         private:
    72                 // returns minimum non-negative count + 1 over type parameters (-1 if none such)
    73                 int minover( std::list<Expression*>& parms ) {
    74                         int mincount = std::numeric_limits<int>::max();
    75                         for ( Expression* parm : parms ) {
    76                                 count = -1;
    77                                 maybeAccept( parm->result, *visitor );
    78                                 if ( count != -1 && count < mincount ) mincount = count;
    79                         }
    80                         return mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    81                 }
    82 
    83         public:
    84                 // look for polymorphic parameters
    85                 void previsit(StructInstType* sty) {
    86                         count = minover( sty->parameters );
    87                 }
    88 
    89                 // look for polymorphic parameters
    90                 void previsit(UnionInstType* uty) {
    91                         count = minover( uty->parameters );
    92                 }
    93 
    94                 // note polymorphic type (which may be specialized)
    95                 // xxx - maybe account for open/closed type variables
    96                 void postvisit(TypeInstType*) { count = 0; }
    97 
    98                 // take minimal specialization over elements
    99                 // xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
    100                 void previsit(TupleType* tty) {
    101                         int mincount = std::numeric_limits<int>::max();
    102                         for ( Type* ty : tty->types ) {
    103                                 count = -1;
    104                                 maybeAccept( ty, *visitor );
    105                                 if ( count != -1 && count < mincount ) mincount = count;
    106                         }
    107                         count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    108                         visit_children = false;
    109                 }
    110         };
    111 
    112         /// Returns the (negated) specialization cost for a given type
    113         int specCost( Type* ty ) {
    114                 PassVisitor<CountSpecs> counter;
    115                 maybeAccept( ty, *counter.pass.visitor );
    116                 return counter.pass.get_count();
    117         }
    11825
    11926namespace {
  • src/ResolvExpr/Unify.cc

    r790d835 rc6b4432  
    3333#include "AST/TypeEnvironment.hpp"
    3434#include "Common/Eval.h"            // for eval
    35 #include "Common/PassVisitor.h"     // for PassVisitor
    3635#include "CommonType.hpp"           // for commonType
    3736#include "FindOpenVars.h"           // for findOpenVars
    3837#include "SpecCost.hpp"             // for SpecCost
    39 #include "SynTree/LinkageSpec.h"    // for C
    40 #include "SynTree/Constant.h"       // for Constant
    41 #include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
    42 #include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
    43 #include "SynTree/Mutator.h"        // for Mutator
    44 #include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
    45 #include "SynTree/Visitor.h"        // for Visitor
    4638#include "Tuples/Tuples.h"          // for isTtype
    47 #include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
    4839#include "typeops.h"                // for flatten, occurs
    4940
     
    5243}
    5344
    54 namespace SymTab {
    55         class Indexer;
    56 }  // namespace SymTab
    57 
    5845// #define DEBUG
    5946
    6047namespace ResolvExpr {
    61 
    62 // Template Helpers:
    63 template< typename Iterator1, typename Iterator2 >
    64 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
    65         for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    66                 Type *commonType = 0;
    67                 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    68                         return false;
    69                 } // if
    70                 commonTypes.push_back( commonType );
    71         } // for
    72         return ( list1Begin == list1End && list2Begin == list2End );
    73 }
    74 
    75 template< typename Iterator1, typename Iterator2 >
    76 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    77         std::list< Type* > commonTypes;
    78         if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
    79                 deleteAll( commonTypes );
    80                 return true;
    81         } else {
    82                 return false;
    83         } // if
    84 }
    85 
    86         struct Unify_old : public WithShortCircuiting {
    87                 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    88 
    89                 bool get_result() const { return result; }
    90 
    91                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    92 
    93                 void postvisit( VoidType * voidType );
    94                 void postvisit( BasicType * basicType );
    95                 void postvisit( PointerType * pointerType );
    96                 void postvisit( ArrayType * arrayType );
    97                 void postvisit( ReferenceType * refType );
    98                 void postvisit( FunctionType * functionType );
    99                 void postvisit( StructInstType * aggregateUseType );
    100                 void postvisit( UnionInstType * aggregateUseType );
    101                 void postvisit( EnumInstType * aggregateUseType );
    102                 void postvisit( TraitInstType * aggregateUseType );
    103                 void postvisit( TypeInstType * aggregateUseType );
    104                 void postvisit( TupleType * tupleType );
    105                 void postvisit( VarArgsType * varArgsType );
    106                 void postvisit( ZeroType * zeroType );
    107                 void postvisit( OneType * oneType );
    108 
    109           private:
    110                 template< typename RefType > void handleRefType( RefType *inst, Type *other );
    111                 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    112 
    113                 bool result;
    114                 Type *type2;                            // inherited
    115                 TypeEnvironment &env;
    116                 AssertionSet &needAssertions;
    117                 AssertionSet &haveAssertions;
    118                 const OpenVarSet &openVars;
    119                 WidenMode widen;
    120                 const SymTab::Indexer &indexer;
    121         };
    122 
    123         /// Attempts an inexact unification of type1 and type2.
    124         /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    125         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    126         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    127 
    128         bool unifyExact(
    129                 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    130                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    131                 WidenMode widen );
    132 
    133         bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    134                 TypeEnvironment newEnv;
    135                 OpenVarSet openVars, closedVars; // added closedVars
    136                 AssertionSet needAssertions, haveAssertions;
    137                 Type * newFirst = first->clone(), * newSecond = second->clone();
    138                 env.apply( newFirst );
    139                 env.apply( newSecond );
    140 
    141                 // do we need to do this? Seems like we do, types should be able to be compatible if they
    142                 // have free variables that can unify
    143                 findOpenVars( newFirst, openVars, closedVars, needAssertions, haveAssertions, false );
    144                 findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
    145 
    146                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    147                 delete newFirst;
    148                 delete newSecond;
    149                 return result;
    150         }
    15148
    15249        bool typesCompatible(
     
    16562
    16663                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
    167         }
    168 
    169         bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    170                 TypeEnvironment newEnv;
    171                 OpenVarSet openVars;
    172                 AssertionSet needAssertions, haveAssertions;
    173                 Type *newFirst = first->clone(), *newSecond = second->clone();
    174                 env.apply( newFirst );
    175                 env.apply( newSecond );
    176                 newFirst->get_qualifiers() = Type::Qualifiers();
    177                 newSecond->get_qualifiers() = Type::Qualifiers();
    178 
    179                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    180                 delete newFirst;
    181                 delete newSecond;
    182                 return result;
    18364        }
    18465
     
    21899                        subSecond,
    219100                        newEnv, need, have, open, noWiden() );
    220         }
    221 
    222         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    223                 OpenVarSet closedVars;
    224                 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
    225                 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    226                 Type *commonType = 0;
    227                 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
    228                         if ( commonType ) {
    229                                 delete commonType;
    230                         } // if
    231                         return true;
    232                 } else {
    233                         return false;
    234                 } // if
    235         }
    236 
    237         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ) {
    238                 OpenVarSet closedVars;
    239                 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
    240                 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    241                 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
    242         }
    243 
    244         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    245 #ifdef DEBUG
    246                 TypeEnvironment debugEnv( env );
    247 #endif
    248                 if ( type1->get_qualifiers() != type2->get_qualifiers() ) {
    249                         return false;
    250                 }
    251 
    252                 bool result;
    253                 TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 );
    254                 TypeInstType *var2 = dynamic_cast< TypeInstType* >( type2 );
    255                 OpenVarSet::const_iterator entry1, entry2;
    256                 if ( var1 ) {
    257                         entry1 = openVars.find( var1->get_name() );
    258                 } // if
    259                 if ( var2 ) {
    260                         entry2 = openVars.find( var2->get_name() );
    261                 } // if
    262                 bool isopen1 = var1 && ( entry1 != openVars.end() );
    263                 bool isopen2 = var2 && ( entry2 != openVars.end() );
    264 
    265                 if ( isopen1 && isopen2 ) {
    266                         if ( entry1->second.kind != entry2->second.kind ) {
    267                                 result = false;
    268                         } else {
    269                                 result = env.bindVarToVar(
    270                                         var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
    271                                         haveAssertions, openVars, widen, indexer );
    272                         }
    273                 } else if ( isopen1 ) {
    274                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
    275                 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
    276                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
    277                 } else {
    278                         PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
    279                         type1->accept( comparator );
    280                         result = comparator.pass.get_result();
    281                 } // if
    282 #ifdef DEBUG
    283                 std::cerr << "============ unifyExact" << std::endl;
    284                 std::cerr << "type1 is ";
    285                 type1->print( std::cerr );
    286                 std::cerr << std::endl << "type2 is ";
    287                 type2->print( std::cerr );
    288                 std::cerr << std::endl << "openVars are ";
    289                 printOpenVarSet( openVars, std::cerr, 8 );
    290                 std::cerr << std::endl << "input env is " << std::endl;
    291                 debugEnv.print( std::cerr, 8 );
    292                 std::cerr << std::endl << "result env is " << std::endl;
    293                 env.print( std::cerr, 8 );
    294                 std::cerr << "result is " << result << std::endl;
    295 #endif
    296                 return result;
    297         }
    298 
    299         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    300                 return unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    301         }
    302 
    303         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
    304                 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    305                 type1->get_qualifiers() = Type::Qualifiers();
    306                 type2->get_qualifiers() = Type::Qualifiers();
    307                 bool result;
    308 #ifdef DEBUG
    309                 std::cerr << "unifyInexact type 1 is ";
    310                 type1->print( std::cerr );
    311                 std::cerr << " type 2 is ";
    312                 type2->print( std::cerr );
    313                 std::cerr << std::endl;
    314 #endif
    315                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
    316 #ifdef DEBUG
    317                         std::cerr << "unifyInexact: no exact unification found" << std::endl;
    318 #endif
    319                         if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
    320                                 common->tq = tq1.unify( tq2 );
    321 #ifdef DEBUG
    322                                 std::cerr << "unifyInexact: common type is ";
    323                                 common->print( std::cerr );
    324                                 std::cerr << std::endl;
    325 #endif
    326                                 result = true;
    327                         } else {
    328 #ifdef DEBUG
    329                                 std::cerr << "unifyInexact: no common type found" << std::endl;
    330 #endif
    331                                 result = false;
    332                         } // if
    333                 } else {
    334                         if ( tq1 != tq2 ) {
    335                                 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
    336                                         common = type1->clone();
    337                                         common->tq = tq1.unify( tq2 );
    338                                         result = true;
    339                                 } else {
    340                                         result = false;
    341                                 } // if
    342                         } else {
    343                                 common = type1->clone();
    344                                 common->tq = tq1.unify( tq2 );
    345                                 result = true;
    346                         } // if
    347                 } // if
    348                 type1->get_qualifiers() = tq1;
    349                 type2->get_qualifiers() = tq2;
    350                 return result;
    351         }
    352 
    353         Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
    354                 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
    355         }
    356 
    357         void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
    358                 result = dynamic_cast< VoidType* >( type2 );
    359         }
    360 
    361         void Unify_old::postvisit(BasicType *basicType) {
    362                 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    363                         result = basicType->get_kind() == otherBasic->get_kind();
    364                 } // if
    365         }
    366 
    367         void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
    368                 AssertionSet::iterator i = assertions.find( assert );
    369                 if ( i != assertions.end() ) {
    370                         i->second.isUsed = true;
    371                 } // if
    372         }
    373 
    374         void markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type ) {
    375                 for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    376                         for ( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
    377                                 markAssertionSet( assertion1, *assert );
    378                                 markAssertionSet( assertion2, *assert );
    379                         } // for
    380                 } // for
    381         }
    382 
    383         void Unify_old::postvisit(PointerType *pointerType) {
    384                 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    385                         result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    386                         markAssertions( haveAssertions, needAssertions, pointerType );
    387                         markAssertions( haveAssertions, needAssertions, otherPointer );
    388                 } // if
    389         }
    390 
    391         void Unify_old::postvisit(ReferenceType *refType) {
    392                 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    393                         result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    394                         markAssertions( haveAssertions, needAssertions, refType );
    395                         markAssertions( haveAssertions, needAssertions, otherRef );
    396                 } // if
    397         }
    398 
    399         void Unify_old::postvisit(ArrayType *arrayType) {
    400                 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    401                 // to unify, array types must both be VLA or both not VLA
    402                 // and must both have a dimension expression or not have a dimension
    403                 if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
    404 
    405                         if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() &&
    406                                 arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) {
    407                                 ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
    408                                 ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( otherArray->get_dimension() );
    409                                 // see C11 Reference Manual 6.7.6.2.6
    410                                 // two array types with size specifiers that are integer constant expressions are
    411                                 // compatible if both size specifiers have the same constant value
    412                                 if ( ce1 && ce2 ) {
    413                                         Constant * c1 = ce1->get_constant();
    414                                         Constant * c2 = ce2->get_constant();
    415 
    416                                         if ( c1->get_value() != c2->get_value() ) {
    417                                                 // does not unify if the dimension is different
    418                                                 return;
    419                                         }
    420                                 }
    421                         }
    422 
    423                         result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    424                 } // if
    425         }
    426 
    427         template< typename Iterator, typename Func >
    428         std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
    429                 std::list< Type * > types;
    430                 for ( ; begin != end; ++begin ) {
    431                         // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple
    432                         flatten( toType( *begin ), back_inserter( types ) );
    433                 }
    434                 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
    435         }
    436 
    437         template< typename Iterator1, typename Iterator2 >
    438         bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    439                 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    440                 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    441                         Type * t1 = (*list1Begin)->get_type();
    442                         Type * t2 = (*list2Begin)->get_type();
    443                         bool isTtype1 = Tuples::isTtype( t1 );
    444                         bool isTtype2 = Tuples::isTtype( t2 );
    445                         // xxx - assumes ttype must be last parameter
    446                         // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
    447                         if ( isTtype1 && ! isTtype2 ) {
    448                                 // combine all of the things in list2, then unify
    449                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    450                         } else if ( isTtype2 && ! isTtype1 ) {
    451                                 // combine all of the things in list1, then unify
    452                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    453                         } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    454                                 return false;
    455                         } // if
    456                 } // for
    457                 // may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype
    458                 if ( list1Begin != list1End ) {
    459                         // try unifying empty tuple type with ttype
    460                         Type * t1 = (*list1Begin)->get_type();
    461                         if ( Tuples::isTtype( t1 ) ) {
    462                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    463                         } else return false;
    464                 } else if ( list2Begin != list2End ) {
    465                         // try unifying empty tuple type with ttype
    466                         Type * t2 = (*list2Begin)->get_type();
    467                         if ( Tuples::isTtype( t2 ) ) {
    468                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    469                         } else return false;
    470                 } else {
    471                         return true;
    472                 } // if
    473         }
    474 
    475         /// Finds ttypes and replaces them with their expansion, if known.
    476         /// This needs to be done so that satisfying ttype assertions is easier.
    477         /// If this isn't done then argument lists can have wildly different
    478         /// size and structure, when they should be compatible.
    479         struct TtypeExpander_old : public WithShortCircuiting {
    480                 TypeEnvironment & tenv;
    481                 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
    482                 void premutate( TypeInstType * ) { visit_children = false; }
    483                 Type * postmutate( TypeInstType * typeInst ) {
    484                         if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
    485                                 // expand ttype parameter into its actual type
    486                                 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
    487                                         delete typeInst;
    488                                         return eqvClass->type->clone();
    489                                 }
    490                         }
    491                         return typeInst;
    492                 }
    493         };
    494 
    495         /// flattens a list of declarations, so that each tuple type has a single declaration.
    496         /// makes use of TtypeExpander to ensure ttypes are flat as well.
    497         void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) {
    498                 dst.clear();
    499                 for ( DeclarationWithType * dcl : src ) {
    500                         PassVisitor<TtypeExpander_old> expander( env );
    501                         dcl->acceptMutator( expander );
    502                         std::list< Type * > types;
    503                         flatten( dcl->get_type(), back_inserter( types ) );
    504                         for ( Type * t : types ) {
    505                                 // outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable.
    506                                 // Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function.
    507                                 t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic);
    508 
    509                                 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    510                         }
    511                         delete dcl;
    512                 }
    513         }
    514 
    515         void Unify_old::postvisit(FunctionType *functionType) {
    516                 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    517                 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
    518                         // flatten the parameter lists for both functions so that tuple structure
    519                         // doesn't affect unification. Must be a clone so that the types don't change.
    520                         std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
    521                         std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
    522                         flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
    523                         flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
    524 
    525                         // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    526                         if (
    527                                         (flatFunc->parameters.size() == flatOther->parameters.size() &&
    528                                                 flatFunc->returnVals.size() == flatOther->returnVals.size())
    529                                         || flatFunc->isTtype()
    530                                         || flatOther->isTtype()
    531                         ) {
    532                                 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    533                                         if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    534 
    535                                                 // the original types must be used in mark assertions, since pointer comparisons are used
    536                                                 markAssertions( haveAssertions, needAssertions, functionType );
    537                                                 markAssertions( haveAssertions, needAssertions, otherFunction );
    538 
    539                                                 result = true;
    540                                         } // if
    541                                 } // if
    542                         } // if
    543                 } // if
    544         }
    545 
    546         template< typename RefType >
    547         void Unify_old::handleRefType( RefType *inst, Type *other ) {
    548                 // check that other type is compatible and named the same
    549                 RefType *otherStruct = dynamic_cast< RefType* >( other );
    550                 result = otherStruct && inst->name == otherStruct->name;
    551         }
    552 
    553         template< typename RefType >
    554         void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
    555                 // Check that other type is compatible and named the same
    556                 handleRefType( inst, other );
    557                 if ( ! result ) return;
    558                 // Check that parameters of types unify, if any
    559                 std::list< Expression* > params = inst->parameters;
    560                 std::list< Expression* > otherParams = ((RefType*)other)->parameters;
    561 
    562                 std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
    563                 for ( ; it != params.end() && jt != otherParams.end(); ++it, ++jt ) {
    564                         TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
    565                         assertf(param, "Aggregate parameters should be type expressions");
    566                         TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt);
    567                         assertf(otherParam, "Aggregate parameters should be type expressions");
    568 
    569                         Type* paramTy = param->get_type();
    570                         Type* otherParamTy = otherParam->get_type();
    571 
    572                         bool tupleParam = Tuples::isTtype( paramTy );
    573                         bool otherTupleParam = Tuples::isTtype( otherParamTy );
    574 
    575                         if ( tupleParam && otherTupleParam ) {
    576                                 ++it; ++jt;  // skip ttype parameters for break
    577                         } else if ( tupleParam ) {
    578                                 // bundle other parameters into tuple to match
    579                                 std::list< Type * > binderTypes;
    580 
    581                                 do {
    582                                         binderTypes.push_back( otherParam->get_type()->clone() );
    583                                         ++jt;
    584 
    585                                         if ( jt == otherParams.end() ) break;
    586 
    587                                         otherParam = dynamic_cast< TypeExpr* >(*jt);
    588                                         assertf(otherParam, "Aggregate parameters should be type expressions");
    589                                 } while (true);
    590 
    591                                 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes };
    592                                 ++it;  // skip ttype parameter for break
    593                         } else if ( otherTupleParam ) {
    594                                 // bundle parameters into tuple to match other
    595                                 std::list< Type * > binderTypes;
    596 
    597                                 do {
    598                                         binderTypes.push_back( param->get_type()->clone() );
    599                                         ++it;
    600 
    601                                         if ( it == params.end() ) break;
    602 
    603                                         param = dynamic_cast< TypeExpr* >(*it);
    604                                         assertf(param, "Aggregate parameters should be type expressions");
    605                                 } while (true);
    606 
    607                                 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes };
    608                                 ++jt;  // skip ttype parameter for break
    609                         }
    610 
    611                         if ( ! unifyExact( paramTy, otherParamTy, env, needAssertions, haveAssertions, openVars, WidenMode(false, false), indexer ) ) {
    612                                 result = false;
    613                                 return;
    614                         }
    615 
    616                         // ttype parameter should be last
    617                         if ( tupleParam || otherTupleParam ) break;
    618                 }
    619                 result = ( it == params.end() && jt == otherParams.end() );
    620         }
    621 
    622         void Unify_old::postvisit(StructInstType *structInst) {
    623                 handleGenericRefType( structInst, type2 );
    624         }
    625 
    626         void Unify_old::postvisit(UnionInstType *unionInst) {
    627                 handleGenericRefType( unionInst, type2 );
    628         }
    629 
    630         void Unify_old::postvisit(EnumInstType *enumInst) {
    631                 handleRefType( enumInst, type2 );
    632         }
    633 
    634         void Unify_old::postvisit(TraitInstType *contextInst) {
    635                 handleRefType( contextInst, type2 );
    636         }
    637 
    638         void Unify_old::postvisit(TypeInstType *typeInst) {
    639                 assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    640                 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
    641                 if ( otherInst && typeInst->get_name() == otherInst->get_name() ) {
    642                         result = true;
    643 ///   } else {
    644 ///     NamedTypeDecl *nt = indexer.lookupType( typeInst->get_name() );
    645 ///     if ( nt ) {
    646 ///       TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
    647 ///       assert( type );
    648 ///       if ( type->get_base() ) {
    649 ///         result = unifyExact( type->get_base(), typeInst, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    650 ///       }
    651 ///     }
    652                 } // if
    653         }
    654 
    655         template< typename Iterator1, typename Iterator2 >
    656         bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    657                 auto get_type = [](Type * t) { return t; };
    658                 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    659                         Type * t1 = *list1Begin;
    660                         Type * t2 = *list2Begin;
    661                         bool isTtype1 = Tuples::isTtype( t1 );
    662                         bool isTtype2 = Tuples::isTtype( t2 );
    663                         // xxx - assumes ttype must be last parameter
    664                         // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
    665                         if ( isTtype1 && ! isTtype2 ) {
    666                                 // combine all of the things in list2, then unify
    667                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    668                         } else if ( isTtype2 && ! isTtype1 ) {
    669                                 // combine all of the things in list1, then unify
    670                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    671                         } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    672                                 return false;
    673                         } // if
    674 
    675                 } // for
    676                 if ( list1Begin != list1End ) {
    677                         // try unifying empty tuple type with ttype
    678                         Type * t1 = *list1Begin;
    679                         if ( Tuples::isTtype( t1 ) ) {
    680                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    681                         } else return false;
    682                 } else if ( list2Begin != list2End ) {
    683                         // try unifying empty tuple type with ttype
    684                         Type * t2 = *list2Begin;
    685                         if ( Tuples::isTtype( t2 ) ) {
    686                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    687                         } else return false;
    688                 } else {
    689                         return true;
    690                 } // if
    691         }
    692 
    693         void Unify_old::postvisit(TupleType *tupleType) {
    694                 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    695                         std::unique_ptr<TupleType> flat1( tupleType->clone() );
    696                         std::unique_ptr<TupleType> flat2( otherTuple->clone() );
    697                         std::list<Type *> types1, types2;
    698 
    699                         PassVisitor<TtypeExpander_old> expander( env );
    700                         flat1->acceptMutator( expander );
    701                         flat2->acceptMutator( expander );
    702 
    703                         flatten( flat1.get(), back_inserter( types1 ) );
    704                         flatten( flat2.get(), back_inserter( types2 ) );
    705 
    706                         result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
    707                 } // if
    708         }
    709 
    710         void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    711                 result = dynamic_cast< VarArgsType* >( type2 );
    712         }
    713 
    714         void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    715                 result = dynamic_cast< ZeroType* >( type2 );
    716         }
    717 
    718         void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
    719                 result = dynamic_cast< OneType* >( type2 );
    720         }
    721 
    722         Type * extractResultType( FunctionType * function ) {
    723                 if ( function->get_returnVals().size() == 0 ) {
    724                         return new VoidType( Type::Qualifiers() );
    725                 } else if ( function->get_returnVals().size() == 1 ) {
    726                         return function->get_returnVals().front()->get_type()->clone();
    727                 } else {
    728                         std::list< Type * > types;
    729                         for ( DeclarationWithType * decl : function->get_returnVals() ) {
    730                                 types.push_back( decl->get_type()->clone() );
    731                         } // for
    732                         return new TupleType( Type::Qualifiers(), types );
    733                 }
    734101        }
    735102
  • src/ResolvExpr/Unify.h

    r790d835 rc6b4432  
    2020#include "AST/Node.hpp"             // for ptr
    2121#include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    22 #include "Common/utility.h"       // for deleteAll
    23 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    24 #include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    2522#include "WidenMode.h"              // for WidenMode
    26 
    27 class Type;
    28 class TypeInstType;
    29 namespace SymTab {
    30         class Indexer;
    31 }
    3223
    3324namespace ast {
     
    3728
    3829namespace ResolvExpr {
    39 
    40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    41 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    42 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    43 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    44 
    45 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    46 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    47 
    48 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    49         TypeEnvironment env;
    50         return typesCompatible( t1, t2, indexer, env );
    51 }
    52 
    53 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    54         TypeEnvironment env;
    55         return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    56 }
    5730
    5831bool unify(
     
    8558        const ast::TypeEnvironment & env = {} );
    8659
    87 /// Creates the type represented by the list of returnVals in a FunctionType.
    88 /// The caller owns the return value.
    89 Type * extractResultType( FunctionType * functionType );
    9060/// Creates or extracts the type represented by returns in a `FunctionType`.
    9161ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
  • src/ResolvExpr/module.mk

    r790d835 rc6b4432  
    1818      ResolvExpr/AdjustExprType.cc \
    1919      ResolvExpr/AdjustExprType.hpp \
    20       ResolvExpr/Alternative.cc \
    21       ResolvExpr/AlternativeFinder.cc \
    22       ResolvExpr/AlternativeFinder.h \
    23       ResolvExpr/Alternative.h \
    2420      ResolvExpr/Candidate.cpp \
    2521      ResolvExpr/CandidateFinder.cpp \
     
    3531      ResolvExpr/CurrentObject.cc \
    3632      ResolvExpr/CurrentObject.h \
    37       ResolvExpr/ExplodedActual.cc \
    38       ResolvExpr/ExplodedActual.h \
    3933      ResolvExpr/ExplodedArg.cpp \
    4034      ResolvExpr/ExplodedArg.hpp \
    4135      ResolvExpr/FindOpenVars.cc \
    4236      ResolvExpr/FindOpenVars.h \
    43       ResolvExpr/Occurs.cc \
    4437      ResolvExpr/PolyCost.cc \
    4538      ResolvExpr/PolyCost.hpp \
     
    5043      ResolvExpr/RenameVars.cc \
    5144      ResolvExpr/RenameVars.h \
    52       ResolvExpr/ResolveAssertions.cc \
    53       ResolvExpr/ResolveAssertions.h \
    5445      ResolvExpr/Resolver.cc \
    5546      ResolvExpr/Resolver.h \
     
    6152      ResolvExpr/SpecCost.cc \
    6253      ResolvExpr/SpecCost.hpp \
    63       ResolvExpr/TypeEnvironment.cc \
    64       ResolvExpr/TypeEnvironment.h \
    6554      ResolvExpr/typeops.h \
    6655      ResolvExpr/Unify.cc \
     
    6958
    7059SRC += $(SRC_RESOLVEXPR) \
    71         ResolvExpr/AlternativePrinter.cc \
    72         ResolvExpr/AlternativePrinter.h \
    7360        ResolvExpr/CandidatePrinter.cpp \
    7461        ResolvExpr/CandidatePrinter.hpp \
  • src/ResolvExpr/typeops.h

    r790d835 rc6b4432  
    1919
    2020#include "AST/Type.hpp"
    21 #include "SynTree/Type.h"
    2221
    2322namespace SymTab {
     
    5251                        std::copy( i.begin(), i.end(), inserter );
    5352                        *out++ = result;
    54                 }
    55         }
    56 
    57         // in Occurs.cc
    58         bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
    59         // new AST version in TypeEnvironment.cpp (only place it was used in old AST)
    60 
    61         template<typename Iter>
    62         bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {
    63                 while ( begin != end ) {
    64                         if ( occurs( ty, *begin, env ) ) return true;
    65                         ++begin;
    66                 }
    67                 return false;
    68         }
    69 
    70         /// flatten tuple type into list of types
    71         template< typename OutputIterator >
    72         void flatten( Type * type, OutputIterator out ) {
    73                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
    74                         for ( Type * t : tupleType->get_types() ) {
    75                                 flatten( t, out );
    76                         }
    77                 } else {
    78                         *out++ = type->clone();
    7953                }
    8054        }
     
    12094                return tupleFromTypes( tys.begin(), tys.end() );
    12195        }
    122 
    123         // in TypeEnvironment.cc
    124         bool isFtype( const Type * type );
    12596} // namespace ResolvExpr
    12697
Note: See TracChangeset for help on using the changeset viewer.