Ignore:
Timestamp:
Jul 20, 2018, 2:13:20 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
new-env
Children:
f89a111
Parents:
d318a18
Message:

Fixed infinite loop bugs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SynTree/TypeSubstitution.cc

    rd318a18 reff03a94  
    1414//
    1515
    16 #include <ostream>  // for ostream, basic_ostream, operator<<, endl
    17 
    18 #include "Type.h"   // for TypeInstType, Type, StructInstType, UnionInstType
     16#include <algorithm>  // for find
     17#include <ostream>    // for ostream, basic_ostream, operator<<, endl
     18
     19#include "Type.h"     // for TypeInstType, Type, StructInstType, UnionInstType
    1920#include "TypeSubstitution.h"
    2021
     
    5960
    6061        // break on not in substitution set
    61         if ( i == typeEnv.end() ) return 0;
     62        if ( i == typeEnv.end() ) return nullptr;
    6263
    6364        // attempt to transitively follow TypeInstType links.
     65        std::vector<std::string> equivNames{ formalType };
    6466        while ( TypeInstType *actualType = dynamic_cast< TypeInstType* >( i->second ) ) {
    6567                const std::string& typeName = actualType->get_name();
    6668
    6769                // break cycles in the transitive follow
    68                 if ( formalType == typeName ) break;
    69 
    70                 // Look for the type this maps to, returning previous mapping if none-such
     70                if ( std::find( equivNames.begin(), equivNames.end(), typeName ) != equivNames.end() ) {
     71                        break;
     72                }
     73                equivNames.emplace_back( typeName );
     74
     75                // Look for the type this maps to, returning previous mapping if none such
    7176                i = typeEnv.find( typeName );
    7277                if ( i == typeEnv.end() ) return actualType;
    7378        }
     79
    7480
    7581        // return type from substitution set
     
    132138                return inst;
    133139        } else {
    134                 // cut off infinite loop for the case where a type is bound to itself.
    135                 // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    136                 // TODO: investigate preventing type variables from being bound to themselves in the first place.
     140                // clear equivalent variables on exit
     141                auto guard = makeFuncGuard( [&]() { equivVars.clear(); } );
     142
    137143                if ( TypeInstType * replacement = dynamic_cast< TypeInstType * >( i->second ) ) {
    138                         if ( inst->name == replacement->name ) {
    139                                 return inst;
    140                         }
    141                 }
     144                        // cut off infinite loop if type is bound to itself (possibly transitively)
     145                        equivVars.push_back( inst );
     146                        auto equiv = std::find_if( equivVars.begin(), equivVars.end(), [&]( TypeInstType* e ) {
     147                                return e->name == replacement->name;
     148                        } );
     149                        if ( equiv != equivVars.end() ) return *equiv;
     150                }
     151
    142152                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    143153                subCount++;
Note: See TracChangeset for help on using the changeset viewer.