Changes in / [9a19608:1867c96]


Ignore:
Location:
src
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r9a19608 r1867c96  
    6565                        // base type
    6666                        ret->result = base;
    67                         add_qualifiers( ret->result, CV::Lvalue );
     67                        add_lvalue( ret->result );
    6868                }
    6969        }
     
    165165        genericSubsitution( aggregate->result ).apply( result );
    166166        // ensure lvalue and appropriate restrictions from aggregate type
    167         add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
     167        result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;
    168168}
    169169
     
    175175        assert( var->get_type() );
    176176        result = var->get_type();
    177         add_qualifiers( result, CV::Lvalue );
     177        add_lvalue( result );
    178178}
    179179
     
    309309        assert( t && i );
    310310        result = t;
    311         add_qualifiers( result, CV::Lvalue );
     311        add_lvalue( result );
    312312}
    313313
     
    326326        // like MemberExpr, TupleIndexExpr is always an lvalue
    327327        result = type->types[ index ];
    328         add_qualifiers( result, CV::Lvalue );
     328        add_lvalue( result );
    329329}
    330330
  • src/AST/Node.hpp

    r9a19608 r1867c96  
    166166        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    167167
    168         /// wrapper for convenient access to strict_dynamic_cast
    169         template<typename o_node_t>
    170         const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }
    171 
    172168        /// Returns a mutable version of the pointer in this node.
    173169        node_t * get_and_mutate();
  • src/AST/Type.hpp

    r9a19608 r1867c96  
    7777};
    7878
    79 /// Clear/reset the qualifiers on this type, cloning only if necessary
     79/// Set the `is_lvalue` qualifier on this type, cloning only if necessary
    8080template< enum Node::ref_type ref_t >
    81 void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
    82         if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;
     81void add_lvalue( ptr_base< Type, ref_t > & p ) {
     82        if ( ! p->qualifiers.is_lvalue ) p.get_and_mutate()->qualifiers.is_lvalue = true;
    8383}
    8484
    85 /// Add the specified qualifiers to this type, cloning only if necessary
     85/// Clear the qualifiers on this type, cloning only if necessary
    8686template< enum Node::ref_type ref_t >
    87 void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
    88         if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q;
    89 }
    90 
    91 /// Remove the specified qualifiers from this type, cloning only if necessary
    92 template< enum Node::ref_type ref_t >
    93 void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
    94         if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q;
     87void clear_qualifiers( ptr_base< Type, ref_t > & p ) {
     88        if ( p->qualifiers != CV::Qualifiers{} ) p.get_and_mutate()->qualifiers = CV::Qualifiers{};
    9589}
    9690
  • src/AST/TypeEnvironment.cpp

    r9a19608 r1867c96  
    235235}
    236236
    237 /// true if a type is a function type
    238 bool isFtype( const Type * type ) {
    239         if ( dynamic_cast< const FunctionType * >( type ) ) {
    240                 return true;
    241         } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
    242                 return typeInst->kind == TypeVar::Ftype;
    243         } else return false;
    244 }
    245 
    246237namespace {
     238        /// true if a type is a function type
     239        bool isFtype( const Type * type ) {
     240                if ( dynamic_cast< const FunctionType * >( type ) ) {
     241                        return true;
     242                } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
     243                        return typeInst->kind == TypeVar::Ftype;
     244                } else return false;
     245        }
     246
    247247        /// true if the given type can be bound to the given type variable
    248248        bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) {
     
    285285                        ptr<Type> common;
    286286                        ptr<Type> newType = it->bound;
    287                         reset_qualifiers( newType, typeInst->qualifiers );
     287                        newType.get_and_mutate()->qualifiers = typeInst->qualifiers;
    288288                        if ( unifyInexact(
    289289                                        newType, target, *this, need, have, open,
     
    291291                                if ( common ) {
    292292                                        it->bound = std::move(common);
    293                                         reset_qualifiers( it->bound );
     293                                        clear_qualifiers( it->bound );
    294294                                }
    295295                        } else return false;
    296296                } else {
    297297                        it->bound = std::move(target);
    298                         reset_qualifiers( it->bound );
     298                        clear_qualifiers( it->bound );
    299299                        it->allowWidening = widen.first && widen.second;
    300300                }
     
    351351                        if ( common ) {
    352352                                c1->bound = std::move(common);
    353                                 reset_qualifiers( c1->bound );
     353                                clear_qualifiers( c1->bound );
    354354                        }
    355355                        c1->data.isComplete |= data.isComplete;
     
    411411                                if ( common ) {
    412412                                        to.bound = std::move(common);
    413                                         reset_qualifiers( to.bound );
     413                                        clear_qualifiers( to.bound );
    414414                                }
    415415                        } else return false; // cannot unify
  • src/AST/TypeEnvironment.hpp

    r9a19608 r1867c96  
    112112        EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d )
    113113        : vars{ v }, bound( b ), allowWidening( w ), data( d ) {
    114                 reset_qualifiers( bound );
     114                clear_qualifiers( bound );
    115115        }
    116116
  • src/ResolvExpr/CommonType.cc

    r9a19608 r1867c96  
    1818#include <utility>                       // for pair
    1919
    20 #include "AST/Decl.hpp"
    21 #include "AST/Type.hpp"
    2220#include "Common/PassVisitor.h"
    2321#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    3735
    3836namespace ResolvExpr {
    39         struct CommonType_old : public WithShortCircuiting {
    40                 CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     37        struct CommonType : public WithShortCircuiting {
     38                CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    4139                Type *get_result() const { return result; }
    4240
     
    9694
    9795        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    98                 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     96                PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    9997
    10098                int depth1 = type1->referenceDepth();
     
    178176        }
    179177
     178        const ast::Type * commonType(
     179                        const ast::Type * type1, const ast::Type * type2, WidenMode widen,
     180                        const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
     181                        const ast::OpenVarSet & open ) {
     182                #warning unimplemented
     183                (void)type1; (void)type2; (void)widen; (void)symtab; (void)env; (void)open;
     184                assert(false);
     185                return nullptr;
     186        }
     187
    180188        // GENERATED START, DO NOT EDIT
    181189        // GENERATED BY BasicTypes-gen.cc
     
    485493        );
    486494
    487         CommonType_old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     495        CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    488496                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    489497        }
    490498
    491         void CommonType_old::postvisit( VoidType * ) {}
    492 
    493         void CommonType_old::postvisit( BasicType *basicType ) {
     499        void CommonType::postvisit( VoidType * ) {}
     500
     501        void CommonType::postvisit( BasicType *basicType ) {
    494502                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    495503                        BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    507515
    508516        template< typename Pointer >
    509         void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
     517        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    510518                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    511519                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    520528        }
    521529
    522         void CommonType_old::postvisit( PointerType *pointerType ) {
     530        void CommonType::postvisit( PointerType *pointerType ) {
    523531                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    524532                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    555563        }
    556564
    557         void CommonType_old::postvisit( ArrayType * ) {}
    558 
    559         void CommonType_old::postvisit( ReferenceType *refType ) {
     565        void CommonType::postvisit( ArrayType * ) {}
     566
     567        void CommonType::postvisit( ReferenceType *refType ) {
    560568                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    561569                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    592600        }
    593601
    594         void CommonType_old::postvisit( FunctionType * ) {}
    595         void CommonType_old::postvisit( StructInstType * ) {}
    596         void CommonType_old::postvisit( UnionInstType * ) {}
    597 
    598         void CommonType_old::postvisit( EnumInstType *enumInstType ) {
     602        void CommonType::postvisit( FunctionType * ) {}
     603        void CommonType::postvisit( StructInstType * ) {}
     604        void CommonType::postvisit( UnionInstType * ) {}
     605
     606        void CommonType::postvisit( EnumInstType *enumInstType ) {
    599607                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    600608                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
     
    603611        }
    604612
    605         void CommonType_old::postvisit( TraitInstType * ) {
    606         }
    607 
    608         void CommonType_old::postvisit( TypeInstType *inst ) {
     613        void CommonType::postvisit( TraitInstType * ) {
     614        }
     615
     616        void CommonType::postvisit( TypeInstType *inst ) {
    609617                if ( widenFirst ) {
    610618                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    628636        }
    629637
    630         void CommonType_old::postvisit( TupleType * ) {}
    631         void CommonType_old::postvisit( VarArgsType * ) {}
    632 
    633         void CommonType_old::postvisit( ZeroType *zeroType ) {
     638        void CommonType::postvisit( TupleType * ) {}
     639        void CommonType::postvisit( VarArgsType * ) {}
     640
     641        void CommonType::postvisit( ZeroType *zeroType ) {
    634642                if ( widenFirst ) {
    635643                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    645653        }
    646654
    647         void CommonType_old::postvisit( OneType *oneType ) {
     655        void CommonType::postvisit( OneType *oneType ) {
    648656                if ( widenFirst ) {
    649657                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    658666                }
    659667        }
    660 
    661         class CommonType_new final : public ast::WithShortCircuiting {
    662                 const ast::Type * type2;
    663                 WidenMode widen;
    664                 const ast::SymbolTable & symtab;
    665                 ast::TypeEnvironment & tenv;
    666                 const ast::OpenVarSet & open;
    667         public:
    668                 ast::ptr< ast::Type > result;
    669 
    670                 CommonType_new(
    671                         const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
    672                         ast::TypeEnvironment & env, const ast::OpenVarSet & o )
    673                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {}
    674 
    675                 void previsit( const ast::Node * ) { visit_children = false; }
    676 
    677                 void postvisit( const ast::VoidType * ) {}
    678 
    679                 void postvisit( const ast::BasicType * basic ) {
    680                         if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    681                                 #warning remove casts when `commonTypes` moved to new AST
    682                                 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ];
    683                                 if (
    684                                         ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers )
    685                                                 || widen.first )
    686                                         && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers )
    687                                                 || widen.second )
    688                                 ) {
    689                                         result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers };
    690                                 }
    691                         } else if (
    692                                 dynamic_cast< const ast::EnumInstType * >( type2 )
    693                                 || dynamic_cast< const ast::ZeroType * >( type2 )
    694                                 || dynamic_cast< const ast::OneType * >( type2 )
    695                         ) {
    696                                 #warning remove casts when `commonTypes` moved to new AST
    697                                 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
    698                                 if (
    699                                         ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
    700                                                 || widen.first )
    701                                         && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
    702                                                 || widen.second )
    703                                 ) {
    704                                         result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
    705                                 }
    706                         }
    707                 }
    708 
    709         private:
    710                 template< typename Pointer >
    711                 void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) {
    712                         const ast::Type * base = oPtr->base;
    713                         if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) {
    714                                 auto entry = open.find( var->name );
    715                                 if ( entry != open.end() ) {
    716                                         ast::AssertionSet need, have;
    717                                         if ( ! tenv.bindVar(
    718                                                 var, voidPtr->base, entry->second, need, have, open, widen, symtab )
    719                                         ) return;
    720                                 }
    721                         }
    722                         result = voidPtr;
    723                         add_qualifiers( result, oPtr->qualifiers );
    724                 }
    725 
    726         public:
    727                 void postvisit( const ast::PointerType * pointer ) {
    728                         if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
    729                                 if (
    730                                         widen.first
    731                                         && pointer2->base.as< ast::VoidType >()
    732                                         && ! ast::isFtype( pointer->base )
    733                                 ) {
    734                                         getCommonWithVoidPointer( pointer2, pointer );
    735                                 } else if (
    736                                         widen.second
    737                                         && pointer->base.as< ast::VoidType >()
    738                                         && ! ast::isFtype( pointer2->base )
    739                                 ) {
    740                                         getCommonWithVoidPointer( pointer, pointer2 );
    741                                 } else if (
    742                                         ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first )
    743                                         && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second )
    744                                 ) {
    745                                         ast::CV::Qualifiers q1 = pointer->base->qualifiers;
    746                                         ast::CV::Qualifiers q2 = pointer2->base->qualifiers;
    747 
    748                                         // force t{1,2} to be cloned if their qualifiers must be stripped, so that
    749                                         // pointer{,2}->base are unchanged
    750                                         ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base };
    751                                         reset_qualifiers( t1 );
    752                                         reset_qualifiers( t2 );
    753                                        
    754                                         ast::AssertionSet have, need;
    755                                         ast::OpenVarSet newOpen{ open };
    756                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    757                                                 result = pointer;
    758                                                 if ( q1.val != q2.val ) {
    759                                                         // reset result->base->qualifiers to be union of two base qualifiers
    760                                                         strict_dynamic_cast< ast::PointerType * >(
    761                                                                 result.get_and_mutate()
    762                                                         )->base.get_and_mutate()->qualifiers = q1 | q2;
    763                                                 }
    764                                         }
    765                                 }
    766                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    767                                 result = pointer;
    768                                 add_qualifiers( result, type2->qualifiers );
    769                         }
    770                 }
    771 
    772                 void postvisit( const ast::ArrayType * ) {}
    773 
    774                 void postvisit( const ast::ReferenceType * ref ) {
    775                         if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    776                                 if (
    777                                         widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base )
    778                                 ) {
    779                                         getCommonWithVoidPointer( ref2, ref );
    780                                 } else if (
    781                                         widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base )
    782                                 ) {
    783                                         getCommonWithVoidPointer( ref, ref2 );
    784                                 } else if (
    785                                         ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first )
    786                                         && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second )
    787                                 ) {
    788                                         ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers;
    789 
    790                                         // force t{1,2} to be cloned if their qualifiers must be stripped, so that
    791                                         // ref{,2}->base are unchanged
    792                                         ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base };
    793                                         reset_qualifiers( t1 );
    794                                         reset_qualifiers( t2 );
    795 
    796                                         ast::AssertionSet have, need;
    797                                         ast::OpenVarSet newOpen{ open };
    798                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    799                                                 result = ref;
    800                                                 if ( q1.val != q2.val ) {
    801                                                         // reset result->base->qualifiers to be union of two base qualifiers
    802                                                         strict_dynamic_cast< ast::ReferenceType * >(
    803                                                                 result.get_and_mutate()
    804                                                         )->base.get_and_mutate()->qualifiers = q1 | q2;
    805                                                 }
    806                                         }
    807                                 }
    808                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    809                                 result = ref;
    810                                 add_qualifiers( result, type2->qualifiers );
    811                         }
    812                 }
    813 
    814                 void postvisit( const ast::FunctionType * ) {}
    815 
    816                 void postvisit( const ast::StructInstType * ) {}
    817 
    818                 void postvisit( const ast::UnionInstType * ) {}
    819 
    820                 void postvisit( const ast::EnumInstType * enumInst ) {
    821                         if (
    822                                 dynamic_cast< const ast::BasicType * >( type2 )
    823                                 || dynamic_cast< const ast::ZeroType * >( type2 )
    824                                 || dynamic_cast< const ast::OneType * >( type2 )
    825                         ) {
    826                                 // reuse BasicType/EnumInstType common type by swapping
    827                                 result = commonType( type2, enumInst, widen, symtab, tenv, open );
    828                         }
    829                 }
    830 
    831                 void postvisit( const ast::TraitInstType * ) {}
    832 
    833                 void postvisit( const ast::TypeInstType * inst ) {
    834                         if ( ! widen.first ) return;
    835                         if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    836                                 if ( const ast::Type * base =
    837                                                 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
    838                                 ) {
    839                                         ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
    840 
    841                                         // force t{1,2} to be cloned if their qualifiers must be mutated
    842                                         ast::ptr< ast::Type > t1{ base }, t2{ type2 };
    843                                         reset_qualifiers( t1, q1 );
    844                                         reset_qualifiers( t2 );
    845 
    846                                         ast::AssertionSet have, need;
    847                                         ast::OpenVarSet newOpen{ open };
    848                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    849                                                 result = type2;
    850                                                 reset_qualifiers( result, q1 | q2 );
    851                                         }
    852                                 }
    853                         }
    854                 }
    855 
    856                 void postvisit( const ast::TupleType * ) {}
    857 
    858                 void postvisit( const ast::VarArgsType * ) {}
    859 
    860                 void postvisit( const ast::ZeroType * zero ) {
    861                         if ( ! widen.first ) return;
    862                         if (
    863                                 dynamic_cast< const ast::BasicType * >( type2 )
    864                                 || dynamic_cast< const ast::PointerType * >( type2 )
    865                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    866                         ) {
    867                                 if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
    868                                         result = type2;
    869                                         add_qualifiers( result, zero->qualifiers );
    870                                 }
    871                         } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) {
    872                                 result = new ast::BasicType{
    873                                         ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers };
    874                         }
    875                 }
    876 
    877                 void postvisit( const ast::OneType * one ) {
    878                         if ( ! widen.first ) return;
    879                         if (
    880                                 dynamic_cast< const ast::BasicType * >( type2 )
    881                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    882                         ) {
    883                                 if ( widen.second || one->qualifiers <= type2->qualifiers ) {
    884                                         result = type2;
    885                                         add_qualifiers( result, one->qualifiers );
    886                                 }
    887                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    888                                 result = new ast::BasicType{
    889                                         ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
    890                         }
    891                 }
    892 
    893         };
    894 
    895         namespace {
    896                 ast::ptr< ast::Type > handleReference(
    897                         const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
    898                         const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    899                         const ast::OpenVarSet & open
    900                 ) {
    901                         ast::ptr<ast::Type> common;
    902                         ast::AssertionSet have, need;
    903                         ast::OpenVarSet newOpen{ open };
    904 
    905                         // need unify to bind type variables
    906                         if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
    907                                 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
    908                                 PRINT(
    909                                         std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    910                                 )
    911                                 if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) {
    912                                         PRINT(
    913                                                 std::cerr << "widen okay" << std::endl;
    914                                         )
    915                                         add_qualifiers( common, q1 | q2 );
    916                                         return common;
    917                                 }
    918                         }
    919 
    920                         PRINT(
    921                                 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
    922                         )
    923                         return { nullptr };
    924                 }
    925         }
    926 
    927         ast::ptr< ast::Type > commonType(
    928                         const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    929                         WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    930                         const ast::OpenVarSet & open
    931         ) {
    932                 unsigned depth1 = type1->referenceDepth();
    933                 unsigned depth2 = type2->referenceDepth();
    934 
    935                 if ( depth1 != depth2 ) {  // implies depth1 > 0 || depth2 > 0
    936                         PRINT(
    937                                 std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl;
    938                         )
    939                         ast::ptr< ast::Type > result;
    940                         const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
    942                        
    943                         if ( depth1 > depth2 ) {
    944                                 assert( ref1 );
    945                                 result = handleReference( ref1->base, type2, widen, symtab, env, open );
    946                         } else {  // implies depth1 < depth2
    947                                 assert( ref2 );
    948                                 result = handleReference( type1, ref2->base, widen, symtab, env, open );
    949                         }
    950 
    951                         if ( result && ref1 ) {
    952                                 // formal is reference, so result should be reference
    953                                 PRINT(
    954                                         std::cerr << "formal is reference; result should be reference" << std::endl;
    955                                 )
    956                                 result = new ast::ReferenceType{ result, ref1->qualifiers };
    957                         }
    958 
    959                         PRINT(
    960                                 std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is "
    961                                 "[" << result << "]" << std::endl;
    962                         )
    963                         return result;
    964                 }
    965                 // otherwise both are reference types of the same depth and this is handled by the visitor
    966                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
    967                 type1->accept( visitor );
    968                 ast::ptr< ast::Type > result = visitor.pass.result;
    969 
    970                 // handling for opaque type declarations (?)
    971                 if ( ! result && widen.second ) {
    972                         if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
    973                                 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    974                                         auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
    975                                         if ( type->base ) {
    976                                                 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    977                                                 ast::AssertionSet have, need;
    978                                                 ast::OpenVarSet newOpen{ open };
    979 
    980                                                 // force t{1,2} to be cloned if its qualifiers must be stripped, so that
    981                                                 // type1 and type->base are left unchanged; calling convention forces
    982                                                 // {type1,type->base}->strong_ref >= 1
    983                                                 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
    984                                                 reset_qualifiers( t1 );
    985                                                 reset_qualifiers( t2, q1 );
    986                                                
    987                                                 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
    988                                                         result = t1;
    989                                                         reset_qualifiers( result, q1 | q2 );
    990                                                 }
    991                                         }
    992                                 }
    993                         }
    994                 }
    995 
    996                 return result;
    997         }
    998 
    999668} // namespace ResolvExpr
    1000669
  • src/ResolvExpr/Unify.cc

    r9a19608 r1867c96  
    136136
    137137                return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     138                        newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );
    139139        }
    140140
     
    173173                env.apply( newFirst );
    174174                env.apply( newSecond );
    175                 reset_qualifiers( newFirst );
    176                 reset_qualifiers( newSecond );
     175                clear_qualifiers( newFirst );
     176                clear_qualifiers( newSecond );
    177177
    178178                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     179                        newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );
    180180        }
    181181
     
    700700        }
    701701
    702         class Unify_new final : public ast::WithShortCircuiting {
     702        class Unify_new : public ast::WithShortCircuiting {
    703703                const ast::Type * type2;
    704704                ast::TypeEnvironment & tenv;
     
    720720                void previsit( const ast::Node * ) { visit_children = false; }
    721721               
    722                 void postvisit( const ast::VoidType * ) {
     722                void previsit( const ast::VoidType * ) {
     723                        visit_children = false;
    723724                        result = dynamic_cast< const ast::VoidType * >( type2 );
    724725                }
    725726
    726                 void postvisit( const ast::BasicType * basic ) {
     727                void previsit( const ast::BasicType * basic ) {
     728                        visit_children = false;
    727729                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    728730                                result = basic->kind == basic2->kind;
     
    730732                }
    731733
    732                 void postvisit( const ast::PointerType * pointer ) {
     734                void previsit( const ast::PointerType * pointer ) {
     735                        visit_children = false;
    733736                        if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
    734737                                result = unifyExact(
    735738                                        pointer->base, pointer2->base, tenv, need, have, open,
    736                                         noWiden(), symtab );
    737                         }
    738                 }
    739 
    740                 void postvisit( const ast::ArrayType * array ) {
     739                                        WidenMode{ false, false }, symtab );
     740                        }
     741                }
     742
     743                void previsit( const ast::ArrayType * array ) {
     744                        visit_children = false;
    741745                        auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );
    742746                        if ( ! array2 ) return;
     
    757761
    758762                        result = unifyExact(
    759                                 array->base, array2->base, tenv, need, have, open, noWiden(),
     763                                array->base, array2->base, tenv, need, have, open, WidenMode{ false, false },
    760764                                symtab );
    761765                }
    762766
    763                 void postvisit( const ast::ReferenceType * ref ) {
     767                void previsit( const ast::ReferenceType * ref ) {
     768                        visit_children = false;
    764769                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    765770                                result = unifyExact(
    766                                         ref->base, ref2->base, tenv, need, have, open, noWiden(),
     771                                        ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false },
    767772                                        symtab );
    768773                        }
     
    778783                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
    779784
    780                         const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     785                        const ast::Type * postmutate( const ast::TypeInstType * typeInst ) {
    781786                                if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
    782787                                        // expand ttype parameter into its actual type
     
    806811                                        // overloaded on outermost mutex and a mutex function has different
    807812                                        // requirements than a non-mutex function
    808                                         remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
     813                                        t.get_and_mutate()->qualifiers
     814                                                -= ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic;
    809815                                        dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
    810816                                }
     
    845851                                        return unifyExact(
    846852                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    847                                                 noWiden(), symtab );
     853                                                WidenMode{ false, false }, symtab );
    848854                                } else if ( ! isTuple1 && isTuple2 ) {
    849855                                        // combine remainder of list1, then unify
    850856                                        return unifyExact(
    851857                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    852                                                 noWiden(), symtab );
     858                                                WidenMode{ false, false }, symtab );
    853859                                }
    854860
    855861                                if ( ! unifyExact(
    856                                         t1, t2, env, need, have, open, noWiden(), symtab )
     862                                        t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )
    857863                                ) return false;
    858864
     
    868874                                return unifyExact(
    869875                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    870                                         noWiden(), symtab );
     876                                        WidenMode{ false, false }, symtab );
    871877                        } else if ( crnt2 != end2 ) {
    872878                                // try unifying empty tuple with ttype
     
    875881                                return unifyExact(
    876882                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    877                                         noWiden(), symtab );
     883                                        WidenMode{ false, false }, symtab );
    878884                        }
    879885
     
    913919
    914920        public:
    915                 void postvisit( const ast::FunctionType * func ) {
     921                void previsit( const ast::FunctionType * func ) {
     922                        visit_children = false;
    916923                        auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );
    917924                        if ( ! func2 ) return;
     
    945952                template< typename RefType >
    946953                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     954                        visit_children = false;
    947955                        // check that the other type is compatible and named the same
    948956                        auto otherInst = dynamic_cast< const RefType * >( other );
     
    10031011
    10041012                                if ( ! unifyExact(
    1005                                                 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
     1013                                                pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) {
    10061014                                        result = false;
    10071015                                        return;
     
    10151023
    10161024        public:
    1017                 void postvisit( const ast::StructInstType * aggrType ) {
     1025                void previsit( const ast::StructInstType * aggrType ) {
    10181026                        handleGenericRefType( aggrType, type2 );
    10191027                }
    10201028
    1021                 void postvisit( const ast::UnionInstType * aggrType ) {
     1029                void previsit( const ast::UnionInstType * aggrType ) {
    10221030                        handleGenericRefType( aggrType, type2 );
    10231031                }
    10241032
    1025                 void postvisit( const ast::EnumInstType * aggrType ) {
     1033                void previsit( const ast::EnumInstType * aggrType ) {
    10261034                        handleRefType( aggrType, type2 );
    10271035                }
    10281036
    1029                 void postvisit( const ast::TraitInstType * aggrType ) {
     1037                void previsit( const ast::TraitInstType * aggrType ) {
    10301038                        handleRefType( aggrType, type2 );
    10311039                }
    10321040
    1033                 void postvisit( const ast::TypeInstType * typeInst ) {
     1041                void previsit( const ast::TypeInstType * typeInst ) {
    10341042                        assert( open.find( typeInst->name ) == open.end() );
    10351043                        handleRefType( typeInst, type2 );
     
    10701078                                        return unifyExact(
    10711079                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1072                                                 noWiden(), symtab );
     1080                                                WidenMode{ false, false }, symtab );
    10731081                                } else if ( ! isTuple1 && isTuple2 ) {
    10741082                                        // combine entirety of list1, then unify
    10751083                                        return unifyExact(
    10761084                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1077                                                 noWiden(), symtab );
     1085                                                WidenMode{ false, false }, symtab );
    10781086                                }
    10791087
    10801088                                if ( ! unifyExact(
    1081                                         t1, t2, env, need, have, open, noWiden(), symtab )
     1089                                        t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )
    10821090                                ) return false;
    10831091
     
    10931101                                return unifyExact(
    10941102                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1095                                                 noWiden(), symtab );
     1103                                                WidenMode{ false, false }, symtab );
    10961104                        } else if ( crnt2 != list2.end() ) {
    10971105                                // try unifying empty tuple with ttype
     
    11021110                                return unifyExact(
    11031111                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1104                                                 noWiden(), symtab );
     1112                                                WidenMode{ false, false }, symtab );
    11051113                        }
    11061114
     
    11091117
    11101118        public:
    1111                 void postvisit( const ast::TupleType * tuple ) {
     1119                void previsit( const ast::TupleType * tuple ) {
     1120                        visit_children = false;
    11121121                        auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );
    11131122                        if ( ! tuple2 ) return;
     
    11231132                }
    11241133
    1125                 void postvisit( const ast::VarArgsType * ) {
     1134                void previsit( const ast::VarArgsType * ) {
     1135                        visit_children = false;
    11261136                        result = dynamic_cast< const ast::VarArgsType * >( type2 );
    11271137                }
    11281138
    1129                 void postvisit( const ast::ZeroType * ) {
     1139                void previsit( const ast::ZeroType * ) {
     1140                        visit_children = false;
    11301141                        result = dynamic_cast< const ast::ZeroType * >( type2 );
    11311142                }
    11321143
    1133                 void postvisit( const ast::OneType * ) {
     1144                void previsit( const ast::OneType * ) {
     1145                        visit_children = false;
    11341146                        result = dynamic_cast< const ast::OneType * >( type2 );
    11351147                }       
     
    11391151                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    11401152        };
    1141 
    1142         bool unify(
    1143                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1144                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1145                         ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    1146         ) {
    1147                 ast::OpenVarSet closed;
    1148                 findOpenVars( type1, open, closed, need, have, FirstClosed );
    1149                 findOpenVars( type2, open, closed, need, have, FirstOpen );
    1150                 return unifyInexact(
    1151                         type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
    1152         }
    11531153
    11541154        bool unifyExact(
     
    11841184
    11851185        bool unifyInexact(
    1186                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1187                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1188                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
    1189                         ast::ptr<ast::Type> & common
     1186                        ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env,
     1187                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1188                        WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    11901189        ) {
    11911190                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     
    11941193                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    11951194                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1196                 reset_qualifiers( t1 );
    1197                 reset_qualifiers( t2 );
     1195                clear_qualifiers( t1 );
     1196                clear_qualifiers( t2 );
    11981197               
    11991198                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     
    12021201                        // if exact unification on unqualified types, try to merge qualifiers
    12031202                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1204                                 common = type1;
    1205                                 reset_qualifiers( common, q1 | q2 );
     1203                                common.set_and_mutate( type1 )->qualifiers = q1 | q2;
    12061204                                return true;
    12071205                        } else {
     
    12131211
    12141212                        // no exact unification, but common type
    1215                         reset_qualifiers( common, q1 | q2 );
     1213                        common.get_and_mutate()->qualifiers = q1 | q2;
    12161214                        return true;
    12171215                } else {
  • src/ResolvExpr/Unify.h

    r9a19608 r1867c96  
    6969        }
    7070
    71         bool unify(
    72                 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    73                 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    74                 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
    75 
    7671        bool unifyExact(
    7772                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    78                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    79                 WidenMode widen, const ast::SymbolTable & symtab );
     73                ast::AssertionSet & need, ast::AssertionSet & have, ast::OpenVarSet & open,
     74                const ast::SymbolTable & symtab );
    8075
    8176        bool unifyInexact(
    82                 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    83                 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    84                 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
    85                 ast::ptr<ast::Type> & common );
     77                ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env,
     78                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     79                WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
    8680
    8781} // namespace ResolvExpr
  • src/ResolvExpr/WidenMode.h

    r9a19608 r1867c96  
    4040                bool first : 1, second : 1;
    4141        };
    42 
    43         static inline WidenMode noWiden() { return { false, false }; }
    4442} // namespace ResolvExpr
    4543
  • src/ResolvExpr/typeops.h

    r9a19608 r1867c96  
    8989
    9090        // in Unify.cc
     91        bool isFtype( Type *type );
    9192        bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    9293        bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    117118        // in CommonType.cc
    118119        Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    119         ast::ptr< ast::Type > commonType(
    120                 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
     120        const ast::Type * commonType(
     121                const ast::Type * type1, const ast::Type * type2, WidenMode widen,
    121122                const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
    122123
     
    176177                return out;
    177178        }
    178 
    179         // in TypeEnvironment.cc
    180         bool isFtype( Type *type );
    181179} // namespace ResolvExpr
    182 
    183 namespace ast {
    184         // in TypeEnvironment.cpp
    185         bool isFtype( const ast::Type * type );
    186 } // namespace ast
    187180
    188181// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.