Changeset 67130fe for src/ResolvExpr


Ignore:
Timestamp:
Jun 4, 2019, 6:39:23 PM (6 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
c6a1e8a
Parents:
7564e10 (diff), 1346914 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/ResolvExpr
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r7564e10 r67130fe  
    2828#include "Alternative.h"           // for AltList, Alternative
    2929#include "AlternativeFinder.h"
     30#include "AST/Expr.hpp"
     31#include "AST/Type.hpp"
    3032#include "Common/SemanticError.h"  // for SemanticError
    3133#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     
    222224                        cost.incReference();
    223225                }
     226        }
     227
     228        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {
     229                if ( expr->result.as< ast::ReferenceType >() ) {
     230                        // cast away reference from expr
     231                        cost.incReference();
     232                        return new ast::CastExpr{ expr->location, expr, expr->result->stripReferences() };
     233                }
     234               
     235                return expr;
    224236        }
    225237
  • src/ResolvExpr/CommonType.cc

    r7564e10 r67130fe  
    1818#include <utility>                       // for pair
    1919
     20#include "AST/Decl.hpp"
     21#include "AST/Type.hpp"
    2022#include "Common/PassVisitor.h"
    2123#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    3537
    3638namespace ResolvExpr {
    37         struct CommonType : public WithShortCircuiting {
    38                 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     39        struct CommonType_old : public WithShortCircuiting {
     40                CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    3941                Type *get_result() const { return result; }
    4042
     
    9496
    9597        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    96                 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     98                PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    9799
    98100                int depth1 = type1->referenceDepth();
     
    483485        );
    484486
    485         CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     487        CommonType_old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    486488                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    487489        }
    488490
    489         void CommonType::postvisit( VoidType * ) {}
    490 
    491         void CommonType::postvisit( BasicType *basicType ) {
     491        void CommonType_old::postvisit( VoidType * ) {}
     492
     493        void CommonType_old::postvisit( BasicType *basicType ) {
    492494                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    493495                        BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    505507
    506508        template< typename Pointer >
    507         void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
     509        void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    508510                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    509511                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    518520        }
    519521
    520         void CommonType::postvisit( PointerType *pointerType ) {
     522        void CommonType_old::postvisit( PointerType *pointerType ) {
    521523                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    522524                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    553555        }
    554556
    555         void CommonType::postvisit( ArrayType * ) {}
    556 
    557         void CommonType::postvisit( ReferenceType *refType ) {
     557        void CommonType_old::postvisit( ArrayType * ) {}
     558
     559        void CommonType_old::postvisit( ReferenceType *refType ) {
    558560                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    559561                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    590592        }
    591593
    592         void CommonType::postvisit( FunctionType * ) {}
    593         void CommonType::postvisit( StructInstType * ) {}
    594         void CommonType::postvisit( UnionInstType * ) {}
    595 
    596         void CommonType::postvisit( EnumInstType *enumInstType ) {
     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 ) {
    597599                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    598600                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
     
    601603        }
    602604
    603         void CommonType::postvisit( TraitInstType * ) {
    604         }
    605 
    606         void CommonType::postvisit( TypeInstType *inst ) {
     605        void CommonType_old::postvisit( TraitInstType * ) {
     606        }
     607
     608        void CommonType_old::postvisit( TypeInstType *inst ) {
    607609                if ( widenFirst ) {
    608610                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    626628        }
    627629
    628         void CommonType::postvisit( TupleType * ) {}
    629         void CommonType::postvisit( VarArgsType * ) {}
    630 
    631         void CommonType::postvisit( ZeroType *zeroType ) {
     630        void CommonType_old::postvisit( TupleType * ) {}
     631        void CommonType_old::postvisit( VarArgsType * ) {}
     632
     633        void CommonType_old::postvisit( ZeroType *zeroType ) {
    632634                if ( widenFirst ) {
    633635                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    643645        }
    644646
    645         void CommonType::postvisit( OneType *oneType ) {
     647        void CommonType_old::postvisit( OneType *oneType ) {
    646648                if ( widenFirst ) {
    647649                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    656658                }
    657659        }
     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
    658999} // namespace ResolvExpr
    6591000
  • src/ResolvExpr/FindOpenVars.cc

    r7564e10 r67130fe  
    1919#include <map>                    // for map<>::mapped_type
    2020
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
    2123#include "Common/PassVisitor.h"
    2224#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
     
    2426
    2527namespace ResolvExpr {
    26         struct FindOpenVars : public WithGuards {
    27                 FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     28        struct FindOpenVars_old : public WithGuards {
     29                FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    2830
    2931                void previsit( PointerType * pointerType );
     
    4042
    4143        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    42                 PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     44                PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    4345                type->accept( finder );
    4446        }
    4547
    46         FindOpenVars::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
     48        FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    4749                : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    4850        }
    4951
    50         void FindOpenVars::common_action( Type *type ) {
     52        void FindOpenVars_old::common_action( Type *type ) {
    5153                if ( nextIsOpen ) {
    5254                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
     
    7678        }
    7779
    78         void FindOpenVars::previsit(PointerType *pointerType) {
     80        void FindOpenVars_old::previsit(PointerType *pointerType) {
    7981                common_action( pointerType );
    8082        }
    8183
    82         void FindOpenVars::previsit(ArrayType *arrayType) {
     84        void FindOpenVars_old::previsit(ArrayType *arrayType) {
    8385                common_action( arrayType );
    8486        }
    8587
    86         void FindOpenVars::previsit(FunctionType *functionType) {
     88        void FindOpenVars_old::previsit(FunctionType *functionType) {
    8789                common_action( functionType );
    8890                nextIsOpen = ! nextIsOpen;
     
    9092        }
    9193
    92         void FindOpenVars::previsit(TupleType *tupleType) {
     94        void FindOpenVars_old::previsit(TupleType *tupleType) {
    9395                common_action( tupleType );
     96        }
     97
     98        namespace {
     99                struct FindOpenVars_new final : public ast::WithGuards {
     100                        ast::OpenVarSet & open;
     101                        ast::OpenVarSet & closed;
     102                        ast::AssertionSet & need;
     103                        ast::AssertionSet & have;
     104                        bool nextIsOpen;
     105
     106                        FindOpenVars_new(
     107                                ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
     108                                ast::AssertionSet & h, FirstMode firstIsOpen )
     109                        : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}
     110
     111                        void previsit( const ast::FunctionType * type ) {
     112                                // mark open/closed variables
     113                                if ( nextIsOpen ) {
     114                                        for ( const ast::TypeDecl * decl : type->forall ) {
     115                                                open[ decl->name ] = ast::TypeDecl::Data{ decl };
     116                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     117                                                        need[ assert ].isUsed = false;
     118                                                }
     119                                        }
     120                                } else {
     121                                        for ( const ast::TypeDecl * decl : type->forall ) {
     122                                                closed[ decl->name ] = ast::TypeDecl::Data{ decl };
     123                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     124                                                        have[ assert ].isUsed = false;
     125                                                }
     126                                        }
     127                                }
     128
     129                                // flip open variables for contained function types
     130                                nextIsOpen = ! nextIsOpen;
     131                                GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
     132                        }
     133
     134                };
     135        }
     136
     137        void findOpenVars(
     138                        const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
     139                        ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
     140                ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
     141                type->accept( finder );
    94142        }
    95143} // namespace ResolvExpr
  • src/ResolvExpr/FindOpenVars.h

    r7564e10 r67130fe  
    1616#pragma once
    1717
     18#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    1819#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    1920
    2021class Type;
     22namespace ast {
     23        class Type;
     24}
    2125
    2226namespace ResolvExpr {
    2327        // Updates open and closed variables and their associated assertions
    2428        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     29
     30        enum FirstMode { FirstClosed, FirstOpen };
     31
     32        // Updates open and closed variables and their associated assertions
     33        void findOpenVars(
     34                const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
     35                ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );
    2536} // namespace ResolvExpr
    2637
  • src/ResolvExpr/ResolveAssertions.cc

    r7564e10 r67130fe  
    3030#include "Common/Indenter.h"        // for Indenter
    3131#include "Common/utility.h"         // for sort_mins
     32#include "GenPoly/GenPoly.h"        // for getFunctionType
    3233#include "ResolvExpr/RenameVars.h"  // for renameTyVars
    3334#include "SymTab/Indexer.h"         // for Indexer
     
    154155                        Cost k = Cost::zero;
    155156                        for ( const auto& assn : x.assns ) {
     157                                // compute conversion cost from satisfying decl to assertion
    156158                                k += computeConversionCost(
    157159                                        assn.match.adjType, assn.decl->get_type(), indexer, x.env );
    158160                               
    159161                                // mark vars+specialization cost on function-type assertions
    160                                 Type* assnType = assn.match.cdata.id->get_type();
    161                                 FunctionType* func;
    162                                 if ( PointerType* ptr = dynamic_cast< PointerType* >( assnType ) ) {
    163                                         func = dynamic_cast< FunctionType* >( ptr->base );
    164                                 } else {
    165                                         func = dynamic_cast< FunctionType* >( assnType );
    166                                 }
     162                                FunctionType* func = GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    167163                                if ( ! func ) continue;
    168164                               
  • src/ResolvExpr/Resolver.cc

    r7564e10 r67130fe  
    77// Resolver.cc --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb 19 18:09:56 2019
    13 // Update Count     : 240
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Wed May 29 11:00:00 2019
     13// Update Count     : 241
    1414//
    1515
     
    2121#include "Alternative.h"                 // for Alternative, AltList
    2222#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
     23#include "CurrentObject.h"               // for CurrentObject
     24#include "RenameVars.h"                  // for RenameVars, global_renamer
     25#include "Resolver.h"
     26#include "ResolvMode.h"                  // for ResolvMode
     27#include "typeops.h"                     // for extractResultType
     28#include "Unify.h"                       // for unify
     29#include "AST/Pass.hpp"
     30#include "AST/SymbolTable.hpp"
    2331#include "Common/PassVisitor.h"          // for PassVisitor
    2432#include "Common/SemanticError.h"        // for SemanticError
    2533#include "Common/utility.h"              // for ValueGuard, group_iterate
    26 #include "CurrentObject.h"               // for CurrentObject
    2734#include "InitTweak/GenInit.h"
    2835#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    29 #include "RenameVars.h"                  // for RenameVars, global_renamer
    3036#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    31 #include "Resolver.h"
    32 #include "ResolvMode.h"                  // for ResolvMode
    3337#include "SymTab/Autogen.h"              // for SizeType
    3438#include "SymTab/Indexer.h"              // for Indexer
     
    4145#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4246#include "Tuples/Tuples.h"
    43 #include "typeops.h"                     // for extractResultType
    44 #include "Unify.h"                       // for unify
    4547#include "Validate/FindSpecialDecls.h"   // for SizeType
    4648
     
    4850
    4951namespace ResolvExpr {
    50         struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
    51                 Resolver() {}
    52                 Resolver( const SymTab::Indexer & other ) {
     52        struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
     53                Resolver_old() {}
     54                Resolver_old( const SymTab::Indexer & other ) {
    5355                        indexer = other;
    5456                }
     
    101103
    102104        void resolve( std::list< Declaration * > translationUnit ) {
    103                 PassVisitor<Resolver> resolver;
     105                PassVisitor<Resolver_old> resolver;
    104106                acceptAll( translationUnit, resolver );
    105107        }
    106108
    107109        void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    108                 PassVisitor<Resolver> resolver( indexer );
     110                PassVisitor<Resolver_old> resolver( indexer );
    109111                maybeAccept( decl, resolver );
    110112        }
     
    402404        }
    403405
    404         void Resolver::previsit( ObjectDecl * objectDecl ) {
    405                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    406                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    407                 // The second analysis changes initContext because of a function type can contain object
    408                 // declarations in the return and parameter types. So each value of initContext is
     406        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
     407                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 
     408                // class-variable initContext is changed multiple time because the LHS is analysed twice. 
     409                // The second analysis changes initContext because of a function type can contain object 
     410                // declarations in the return and parameter types. So each value of initContext is 
    409411                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    410412                GuardValue( currentObject );
     
    418420
    419421        template< typename PtrType >
    420         void Resolver::handlePtrType( PtrType * type ) {
     422        void Resolver_old::handlePtrType( PtrType * type ) {
    421423                if ( type->get_dimension() ) {
    422424                        findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     
    424426        }
    425427
    426         void Resolver::previsit( ArrayType * at ) {
     428        void Resolver_old::previsit( ArrayType * at ) {
    427429                handlePtrType( at );
    428430        }
    429431
    430         void Resolver::previsit( PointerType * pt ) {
     432        void Resolver_old::previsit( PointerType * pt ) {
    431433                handlePtrType( pt );
    432434        }
    433435
    434         void Resolver::previsit( FunctionDecl * functionDecl ) {
     436        void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    435437#if 0
    436438                std::cerr << "resolver visiting functiondecl ";
     
    442444        }
    443445
    444         void Resolver::postvisit( FunctionDecl * functionDecl ) {
    445                 // default value expressions have an environment which shouldn't be there and trips up
     446        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
     447                // default value expressions have an environment which shouldn't be there and trips up 
    446448                // later passes.
    447449                // xxx - it might be necessary to somehow keep the information from this environment, but I
     
    457459        }
    458460
    459         void Resolver::previsit( EnumDecl * ) {
     461        void Resolver_old::previsit( EnumDecl * ) {
    460462                // in case we decide to allow nested enums
    461463                GuardValue( inEnumDecl );
     
    463465        }
    464466
    465         void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     467        void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
    466468                findIntegralExpression( assertDecl->condition, indexer );
    467469        }
    468470
    469         void Resolver::previsit( ExprStmt * exprStmt ) {
     471        void Resolver_old::previsit( ExprStmt * exprStmt ) {
    470472                visit_children = false;
    471473                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     
    473475        }
    474476
    475         void Resolver::previsit( AsmExpr * asmExpr ) {
     477        void Resolver_old::previsit( AsmExpr * asmExpr ) {
    476478                visit_children = false;
    477479                findVoidExpression( asmExpr->operand, indexer );
     
    481483        }
    482484
    483         void Resolver::previsit( AsmStmt * asmStmt ) {
     485        void Resolver_old::previsit( AsmStmt * asmStmt ) {
    484486                visit_children = false;
    485487                acceptAll( asmStmt->get_input(), *visitor );
     
    487489        }
    488490
    489         void Resolver::previsit( IfStmt * ifStmt ) {
     491        void Resolver_old::previsit( IfStmt * ifStmt ) {
    490492                findIntegralExpression( ifStmt->condition, indexer );
    491493        }
    492494
    493         void Resolver::previsit( WhileStmt * whileStmt ) {
     495        void Resolver_old::previsit( WhileStmt * whileStmt ) {
    494496                findIntegralExpression( whileStmt->condition, indexer );
    495497        }
    496498
    497         void Resolver::previsit( ForStmt * forStmt ) {
     499        void Resolver_old::previsit( ForStmt * forStmt ) {
    498500                if ( forStmt->condition ) {
    499501                        findIntegralExpression( forStmt->condition, indexer );
     
    505507        }
    506508
    507         void Resolver::previsit( SwitchStmt * switchStmt ) {
     509        void Resolver_old::previsit( SwitchStmt * switchStmt ) {
    508510                GuardValue( currentObject );
    509511                findIntegralExpression( switchStmt->condition, indexer );
     
    512514        }
    513515
    514         void Resolver::previsit( CaseStmt * caseStmt ) {
     516        void Resolver_old::previsit( CaseStmt * caseStmt ) {
    515517                if ( caseStmt->condition ) {
    516518                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     
    531533        }
    532534
    533         void Resolver::previsit( BranchStmt * branchStmt ) {
     535        void Resolver_old::previsit( BranchStmt * branchStmt ) {
    534536                visit_children = false;
    535537                // must resolve the argument for a computed goto
     
    542544        }
    543545
    544         void Resolver::previsit( ReturnStmt * returnStmt ) {
     546        void Resolver_old::previsit( ReturnStmt * returnStmt ) {
    545547                visit_children = false;
    546548                if ( returnStmt->expr ) {
     
    549551        }
    550552
    551         void Resolver::previsit( ThrowStmt * throwStmt ) {
     553        void Resolver_old::previsit( ThrowStmt * throwStmt ) {
    552554                visit_children = false;
    553555                // TODO: Replace *exception type with &exception type.
     
    561563        }
    562564
    563         void Resolver::previsit( CatchStmt * catchStmt ) {
     565        void Resolver_old::previsit( CatchStmt * catchStmt ) {
    564566                if ( catchStmt->cond ) {
    565567                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     
    576578        }
    577579
    578         void Resolver::previsit( WaitForStmt * stmt ) {
     580        void Resolver_old::previsit( WaitForStmt * stmt ) {
    579581                visit_children = false;
    580582
     
    782784        }
    783785
    784         void Resolver::previsit( SingleInit * singleInit ) {
     786        void Resolver_old::previsit( SingleInit * singleInit ) {
    785787                visit_children = false;
    786788                // resolve initialization using the possibilities as determined by the currentObject cursor
     
    834836        }
    835837
    836         void Resolver::previsit( ListInit * listInit ) {
     838        void Resolver_old::previsit( ListInit * listInit ) {
    837839                visit_children = false;
    838840                // move cursor into brace-enclosed initializer-list
     
    869871
    870872        // ConstructorInit - fall back on C-style initializer
    871         void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
     873        void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
    872874                // could not find valid constructor, or found an intrinsic constructor
    873875                // fall back on C-style initializer
     
    882884        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    883885                assert( ctorInit );
    884                 PassVisitor<Resolver> resolver( indexer );
     886                PassVisitor<Resolver_old> resolver( indexer );
    885887                ctorInit->accept( resolver );
    886888        }
     
    888890        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    889891                assert( stmtExpr );
    890                 PassVisitor<Resolver> resolver( indexer );
     892                PassVisitor<Resolver_old> resolver( indexer );
    891893                stmtExpr->accept( resolver );
    892894                stmtExpr->computeResult();
     
    894896        }
    895897
    896         void Resolver::previsit( ConstructorInit * ctorInit ) {
     898        void Resolver_old::previsit( ConstructorInit * ctorInit ) {
    897899                visit_children = false;
    898900                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     
    928930                // }
    929931        }
     932
     933        ///////////////////////////////////////////////////////////////////////////
     934        //
     935        // *** NEW RESOLVER ***
     936        //
     937        ///////////////////////////////////////////////////////////////////////////
     938
     939        class Resolver_new final
     940        : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>,
     941          public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> {
     942                 
     943        public:
     944                Resolver_new() = default;
     945                Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/ }
     946
     947                void previsit( ast::FunctionDecl * functionDecl );
     948                ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl );
     949                void previsit( ast::ObjectDecl * objectDecl );
     950                void previsit( ast::EnumDecl * enumDecl );
     951                void previsit( ast::StaticAssertDecl * assertDecl );
     952
     953                void previsit( ast::ArrayType * at );
     954                void previsit( ast::PointerType * pt );
     955
     956                void previsit( ast::ExprStmt * exprStmt );
     957                void previsit( ast::AsmExpr * asmExpr );
     958                void previsit( ast::AsmStmt * asmStmt );
     959                void previsit( ast::IfStmt * ifStmt );
     960                void previsit( ast::WhileStmt * whileStmt );
     961                void previsit( ast::ForStmt * forStmt );
     962                void previsit( ast::SwitchStmt * switchStmt );
     963                void previsit( ast::CaseStmt * caseStmt );
     964                void previsit( ast::BranchStmt * branchStmt );
     965                void previsit( ast::ReturnStmt * returnStmt );
     966                void previsit( ast::ThrowStmt * throwStmt );
     967                void previsit( ast::CatchStmt * catchStmt );
     968                void previsit( ast::WaitForStmt * stmt );
     969
     970                void previsit( ast::SingleInit * singleInit );
     971                void previsit( ast::ListInit * listInit );
     972                void previsit( ast::ConstructorInit * ctorInit );
     973        };
     974
     975        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     976                ast::Pass<Resolver_new> resolver;
     977                accept_all( translationUnit, resolver );
     978        }
     979
     980        void previsit( ast::FunctionDecl * functionDecl ) {
     981                #warning unimplemented; Resolver port in progress
     982                (void)functionDecl;
     983                assert(false);
     984        }
     985
     986        ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl ) {
     987                #warning unimplemented; Resolver port in progress
     988                (void)functionDecl;
     989                assert(false);
     990                return nullptr;
     991        }
     992
     993        void previsit( ast::ObjectDecl * objectDecl ) {
     994                #warning unimplemented; Resolver port in progress
     995                (void)objectDecl;
     996                assert(false);
     997        }
     998
     999        void previsit( ast::EnumDecl * enumDecl ) {
     1000                #warning unimplemented; Resolver port in progress
     1001                (void)enumDecl;
     1002                assert(false);
     1003        }
     1004
     1005        void previsit( ast::StaticAssertDecl * assertDecl ) {
     1006                #warning unimplemented; Resolver port in progress
     1007                (void)assertDecl;
     1008                assert(false);
     1009        }
     1010
     1011        void previsit( ast::ArrayType * at ) {
     1012                #warning unimplemented; Resolver port in progress
     1013                (void)at;
     1014                assert(false);
     1015        }
     1016
     1017        void previsit( ast::PointerType * pt ) {
     1018                #warning unimplemented; Resolver port in progress
     1019                (void)pt;
     1020                assert(false);
     1021        }
     1022
     1023        void previsit( ast::ExprStmt * exprStmt ) {
     1024                #warning unimplemented; Resolver port in progress
     1025                (void)exprStmt;
     1026                assert(false);
     1027        }
     1028
     1029        void previsit( ast::AsmExpr * asmExpr ) {
     1030                #warning unimplemented; Resolver port in progress
     1031                (void)asmExpr;
     1032                assert(false);
     1033        }
     1034
     1035        void previsit( ast::AsmStmt * asmStmt ) {
     1036                #warning unimplemented; Resolver port in progress
     1037                (void)asmStmt;
     1038                assert(false);
     1039        }
     1040
     1041        void previsit( ast::IfStmt * ifStmt ) {
     1042                #warning unimplemented; Resolver port in progress
     1043                (void)ifStmt;
     1044                assert(false);
     1045        }
     1046
     1047        void previsit( ast::WhileStmt * whileStmt ) {
     1048                #warning unimplemented; Resolver port in progress
     1049                (void)whileStmt;
     1050                assert(false);
     1051        }
     1052
     1053        void previsit( ast::ForStmt * forStmt ) {
     1054                #warning unimplemented; Resolver port in progress
     1055                (void)forStmt;
     1056                assert(false);
     1057        }
     1058
     1059        void previsit( ast::SwitchStmt * switchStmt ) {
     1060                #warning unimplemented; Resolver port in progress
     1061                (void)switchStmt;
     1062                assert(false);
     1063        }
     1064
     1065        void previsit( ast::CaseStmt * caseStmt ) {
     1066                #warning unimplemented; Resolver port in progress
     1067                (void)caseStmt;
     1068                assert(false);
     1069        }
     1070
     1071        void previsit( ast::BranchStmt * branchStmt ) {
     1072                #warning unimplemented; Resolver port in progress
     1073                (void)branchStmt;
     1074                assert(false);
     1075        }
     1076
     1077        void previsit( ast::ReturnStmt * returnStmt ) {
     1078                #warning unimplemented; Resolver port in progress
     1079                (void)returnStmt;
     1080                assert(false);
     1081        }
     1082
     1083        void previsit( ast::ThrowStmt * throwStmt ) {
     1084                #warning unimplemented; Resolver port in progress
     1085                (void)throwStmt;
     1086                assert(false);
     1087        }
     1088
     1089        void previsit( ast::CatchStmt * catchStmt ) {
     1090                #warning unimplemented; Resolver port in progress
     1091                (void)catchStmt;
     1092                assert(false);
     1093        }
     1094
     1095        void previsit( ast::WaitForStmt * stmt ) {
     1096                #warning unimplemented; Resolver port in progress
     1097                (void)stmt;
     1098                assert(false);
     1099        }
     1100
     1101        void previsit( ast::SingleInit * singleInit ) {
     1102                #warning unimplemented; Resolver port in progress
     1103                (void)singleInit;
     1104                assert(false);
     1105        }
     1106
     1107        void previsit( ast::ListInit * listInit ) {
     1108                #warning unimplemented; Resolver port in progress
     1109                (void)listInit;
     1110                assert(false);
     1111        }
     1112
     1113        void previsit( ast::ConstructorInit * ctorInit ) {
     1114                #warning unimplemented; Resolver port in progress
     1115                (void)ctorInit;
     1116                assert(false);
     1117        }
     1118
    9301119} // namespace ResolvExpr
    9311120
  • src/ResolvExpr/Resolver.h

    r7564e10 r67130fe  
    1616#pragma once
    1717
    18 #include <list>  // for list
     18#include <list>          // for list
     19#include <AST/Node.hpp>  // for ptr
    1920
    2021class ConstructorInit;
     
    2324class StmtExpr;
    2425namespace SymTab {
    25 class Indexer;
    26 }  // namespace SymTab
     26        class Indexer;
     27} // namespace SymTab
     28
     29namespace ast {
     30        class Decl;
     31} // namespace ast
    2732
    2833namespace ResolvExpr {
     
    4045        /// Resolves with-stmts and with-clauses on functions
    4146        void resolveWithExprs( std::list< Declaration * > & translationUnit );
     47
     48        /// Checks types and binds syntactic constructs to typed representations
     49        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
    4250} // namespace ResolvExpr
    4351
  • src/ResolvExpr/TypeEnvironment.cc

    r7564e10 r67130fe  
    205205                                // attempt to unify bound types
    206206                                std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
    207                                 WidenMode widenMode{ to.allowWidening, from.allowWidening };
     207                                WidenMode widen{ to.allowWidening, from.allowWidening };
    208208                                Type* common = nullptr;
    209209                                AssertionSet need, have;
    210                                 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) {
     210                                if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) {
    211211                                        // unifies, set common type if necessary
    212212                                        if ( common ) {
     
    343343        }
    344344
    345         bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     345        bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    346346
    347347                // remove references from other, so that type variables can only bind to value types
     
    362362                                std::unique_ptr< Type > newType( curClass->type->clone() );
    363363                                newType->get_qualifiers() = typeInst->get_qualifiers();
    364                                 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     364                                if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    365365                                        if ( common ) {
    366366                                                common->get_qualifiers() = Type::Qualifiers{};
     
    372372                                newType->get_qualifiers() = Type::Qualifiers{};
    373373                                curClass->set_type( newType );
    374                                 curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     374                                curClass->allowWidening = widen.first && widen.second;
    375375                        } // if
    376376                } else {
     
    379379                        newClass.type = bindTo->clone();
    380380                        newClass.type->get_qualifiers() = Type::Qualifiers();
    381                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     381                        newClass.allowWidening = widen.first && widen.second;
    382382                        newClass.data = data;
    383383                        env.push_back( std::move(newClass) );
     
    388388        bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2,
    389389                        TypeDecl::Data && data, AssertionSet &need, AssertionSet &have,
    390                         const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     390                        const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    391391
    392392                auto class1 = internal_lookup( var1->get_name() );
     
    395395                // exit early if variables already bound together
    396396                if ( class1 != env.end() && class1 == class2 ) {
    397                         class1->allowWidening &= widenMode;
     397                        class1->allowWidening &= widen;
    398398                        return true;
    399399                }
     
    408408                                type1 = class1->type;
    409409                        } // if
    410                         widen1 = widenMode.widenFirst && class1->allowWidening;
     410                        widen1 = widen.first && class1->allowWidening;
    411411                } // if
    412412                if ( class2 != env.end() ) {
     
    415415                                type2 = class2->type;
    416416                        } // if
    417                         widen2 = widenMode.widenSecond && class2->allowWidening;
     417                        widen2 = widen.second && class2->allowWidening;
    418418                } // if
    419419
  • src/ResolvExpr/TypeEnvironment.h

    r7564e10 r67130fe  
    136136                /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
    137137                /// the class if needed. Returns false on failure.
    138                 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     138                bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    139139               
    140140                /// Binds the type classes represented by `var1` and `var2` together; will add
    141141                /// one or both classes if needed. Returns false on failure.
    142                 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     142                bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    143143
    144144                /// Disallows widening for all bindings in the environment
  • src/ResolvExpr/Unify.cc

    r7564e10 r67130fe  
    1414//
    1515
    16 #include <cassert>                // for assertf, assert
    17 #include <iterator>               // for back_insert_iterator, back_inserter
    18 #include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
    19 #include <memory>                 // for unique_ptr
    20 #include <set>                    // for set
    21 #include <string>                 // for string, operator==, operator!=, bas...
    22 #include <utility>                // for pair, move
     16#include "Unify.h"
     17
     18#include <cassert>                  // for assertf, assert
     19#include <iterator>                 // for back_insert_iterator, back_inserter
     20#include <map>                      // for _Rb_tree_const_iterator, _Rb_tree_i...
     21#include <memory>                   // for unique_ptr
     22#include <set>                      // for set
     23#include <string>                   // for string, operator==, operator!=, bas...
     24#include <utility>                  // for pair, move
    2325#include <vector>
    2426
     27#include "AST/Decl.hpp"
    2528#include "AST/Node.hpp"
     29#include "AST/Pass.hpp"
    2630#include "AST/Type.hpp"
    27 #include "Common/PassVisitor.h"   // for PassVisitor
    28 #include "FindOpenVars.h"         // for findOpenVars
    29 #include "Parser/LinkageSpec.h"   // for C
    30 #include "SynTree/Constant.h"     // for Constant
    31 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data, Declarati...
    32 #include "SynTree/Expression.h"   // for TypeExpr, Expression, ConstantExpr
    33 #include "SynTree/Mutator.h"      // for Mutator
    34 #include "SynTree/Type.h"         // for Type, TypeInstType, FunctionType
    35 #include "SynTree/Visitor.h"      // for Visitor
    36 #include "Tuples/Tuples.h"        // for isTtype
    37 #include "TypeEnvironment.h"      // for EqvClass, AssertionSet, OpenVarSet
    38 #include "Unify.h"
    39 #include "typeops.h"              // for flatten, occurs, commonType
     31#include "AST/TypeEnvironment.hpp"
     32#include "Common/PassVisitor.h"     // for PassVisitor
     33#include "FindOpenVars.h"           // for findOpenVars
     34#include "Parser/LinkageSpec.h"     // for C
     35#include "SynTree/Constant.h"       // for Constant
     36#include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
     37#include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
     38#include "SynTree/Mutator.h"        // for Mutator
     39#include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
     40#include "SynTree/Visitor.h"        // for Visitor
     41#include "Tuples/Tuples.h"          // for isTtype
     42#include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
     43#include "typeops.h"                // for flatten, occurs, commonType
     44
     45namespace ast {
     46        class SymbolTable;
     47}
    4048
    4149namespace SymTab {
     
    4755namespace ResolvExpr {
    4856
    49         struct Unify : public WithShortCircuiting {
    50                 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     57        struct Unify_old : public WithShortCircuiting {
     58                Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    5159
    5260                bool get_result() const { return result; }
     
    8088                AssertionSet &haveAssertions;
    8189                const OpenVarSet &openVars;
    82                 WidenMode widenMode;
     90                WidenMode widen;
    8391                const SymTab::Indexer &indexer;
    8492        };
     
    8694        /// Attempts an inexact unification of type1 and type2.
    8795        /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    88         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    89         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     96        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
     97        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
     98
     99        bool unifyExact(
     100                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     101                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     102                WidenMode widen, const ast::SymbolTable & symtab );
    90103
    91104        bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     
    106119                delete newSecond;
    107120                return result;
     121        }
     122
     123        bool typesCompatible(
     124                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     125                        const ast::TypeEnvironment & env ) {
     126                ast::TypeEnvironment newEnv;
     127                ast::OpenVarSet open, closed;
     128                ast::AssertionSet need, have;
     129
     130                ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
     131                env.apply( newFirst );
     132                env.apply( newSecond );
     133
     134                findOpenVars( newFirst, open, closed, need, have, FirstClosed );
     135                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
     136
     137                return unifyExact(
     138                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    108139        }
    109140
     
    132163        }
    133164
     165        bool typesCompatibleIgnoreQualifiers(
     166                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     167                        const ast::TypeEnvironment & env ) {
     168                ast::TypeEnvironment newEnv;
     169                ast::OpenVarSet open;
     170                ast::AssertionSet need, have;
     171               
     172                ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
     173                env.apply( newFirst );
     174                env.apply( newSecond );
     175                reset_qualifiers( newFirst );
     176                reset_qualifiers( newSecond );
     177
     178                return unifyExact(
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     180        }
     181
    134182        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    135183                OpenVarSet closedVars;
     
    154202        }
    155203
    156         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     204        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    157205#ifdef DEBUG
    158206                TypeEnvironment debugEnv( env );
     
    181229                                result = env.bindVarToVar(
    182230                                        var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
    183                                         haveAssertions, openVars, widenMode, indexer );
     231                                        haveAssertions, openVars, widen, indexer );
    184232                        }
    185233                } else if ( isopen1 ) {
    186                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    187                 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    188                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     234                        result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
     235                } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
     236                        result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
    189237                } else {
    190                         PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     238                        PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
    191239                        type1->accept( comparator );
    192240                        result = comparator.pass.get_result();
     
    213261        }
    214262
    215         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ) {
     263        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
    216264                Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    217265                type1->get_qualifiers() = Type::Qualifiers();
     
    225273                std::cerr << std::endl;
    226274#endif
    227                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
     275                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
    228276#ifdef DEBUG
    229277                        std::cerr << "unifyInexact: no exact unification found" << std::endl;
    230278#endif
    231                         if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
     279                        if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
    232280                                common->get_qualifiers() = tq1 | tq2;
    233281#ifdef DEBUG
     
    245293                } else {
    246294                        if ( tq1 != tq2 ) {
    247                                 if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
     295                                if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
    248296                                        common = type1->clone();
    249297                                        common->get_qualifiers() = tq1 | tq2;
     
    263311        }
    264312
    265         Unify::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
    266                 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widenMode( widenMode ), indexer( indexer ) {
    267         }
    268 
    269         void Unify::postvisit( __attribute__((unused)) VoidType *voidType) {
     313        Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
     314                : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
     315        }
     316
     317        void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
    270318                result = dynamic_cast< VoidType* >( type2 );
    271319        }
    272320
    273         void Unify::postvisit(BasicType *basicType) {
     321        void Unify_old::postvisit(BasicType *basicType) {
    274322                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    275323                        result = basicType->get_kind() == otherBasic->get_kind();
     
    299347        }
    300348
    301         void Unify::postvisit(PointerType *pointerType) {
     349        void Unify_old::postvisit(PointerType *pointerType) {
    302350                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    303351                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    307355        }
    308356
    309         void Unify::postvisit(ReferenceType *refType) {
     357        void Unify_old::postvisit(ReferenceType *refType) {
    310358                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    311359                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    315363        }
    316364
    317         void Unify::postvisit(ArrayType *arrayType) {
     365        void Unify_old::postvisit(ArrayType *arrayType) {
    318366                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    319367                // to unify, array types must both be VLA or both not VLA
     
    395443        /// If this isn't done then argument lists can have wildly different
    396444        /// size and structure, when they should be compatible.
    397         struct TtypeExpander : public WithShortCircuiting {
     445        struct TtypeExpander_old : public WithShortCircuiting {
    398446                TypeEnvironment & tenv;
    399                 TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
     447                TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
    400448                void premutate( TypeInstType * ) { visit_children = false; }
    401449                Type * postmutate( TypeInstType * typeInst ) {
     
    416464                dst.clear();
    417465                for ( DeclarationWithType * dcl : src ) {
    418                         PassVisitor<TtypeExpander> expander( env );
     466                        PassVisitor<TtypeExpander_old> expander( env );
    419467                        dcl->acceptMutator( expander );
    420468                        std::list< Type * > types;
     
    431479        }
    432480
    433         void Unify::postvisit(FunctionType *functionType) {
     481        void Unify_old::postvisit(FunctionType *functionType) {
    434482                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    435483                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    442490
    443491                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    444                         if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
     492                        if (
     493                                        (flatFunc->parameters.size() == flatOther->parameters.size() &&
     494                                                flatFunc->returnVals.size() == flatOther->returnVals.size())
     495                                        || flatFunc->isTtype()
     496                                        || flatOther->isTtype()
     497                        ) {
    445498                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    446499                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     
    458511
    459512        template< typename RefType >
    460         void Unify::handleRefType( RefType *inst, Type *other ) {
     513        void Unify_old::handleRefType( RefType *inst, Type *other ) {
    461514                // check that other type is compatible and named the same
    462515                RefType *otherStruct = dynamic_cast< RefType* >( other );
     
    465518
    466519        template< typename RefType >
    467         void Unify::handleGenericRefType( RefType *inst, Type *other ) {
     520        void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
    468521                // Check that other type is compatible and named the same
    469522                handleRefType( inst, other );
     
    533586        }
    534587
    535         void Unify::postvisit(StructInstType *structInst) {
     588        void Unify_old::postvisit(StructInstType *structInst) {
    536589                handleGenericRefType( structInst, type2 );
    537590        }
    538591
    539         void Unify::postvisit(UnionInstType *unionInst) {
     592        void Unify_old::postvisit(UnionInstType *unionInst) {
    540593                handleGenericRefType( unionInst, type2 );
    541594        }
    542595
    543         void Unify::postvisit(EnumInstType *enumInst) {
     596        void Unify_old::postvisit(EnumInstType *enumInst) {
    544597                handleRefType( enumInst, type2 );
    545598        }
    546599
    547         void Unify::postvisit(TraitInstType *contextInst) {
     600        void Unify_old::postvisit(TraitInstType *contextInst) {
    548601                handleRefType( contextInst, type2 );
    549602        }
    550603
    551         void Unify::postvisit(TypeInstType *typeInst) {
     604        void Unify_old::postvisit(TypeInstType *typeInst) {
    552605                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    553606                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    604657        }
    605658
    606         void Unify::postvisit(TupleType *tupleType) {
     659        void Unify_old::postvisit(TupleType *tupleType) {
    607660                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    608661                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    610663                        std::list<Type *> types1, types2;
    611664
    612                         PassVisitor<TtypeExpander> expander( env );
     665                        PassVisitor<TtypeExpander_old> expander( env );
    613666                        flat1->acceptMutator( expander );
    614667                        flat2->acceptMutator( expander );
     
    621674        }
    622675
    623         void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
     676        void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    624677                result = dynamic_cast< VarArgsType* >( type2 );
    625678        }
    626679
    627         void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
     680        void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    628681                result = dynamic_cast< ZeroType* >( type2 );
    629682        }
    630683
    631         void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
     684        void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
    632685                result = dynamic_cast< OneType* >( type2 );
    633686        }
     
    647700        }
    648701
     702        class Unify_new final : public ast::WithShortCircuiting {
     703                const ast::Type * type2;
     704                ast::TypeEnvironment & tenv;
     705                ast::AssertionSet & need;
     706                ast::AssertionSet & have;
     707                const ast::OpenVarSet & open;
     708                WidenMode widen;
     709                const ast::SymbolTable & symtab;
     710        public:
     711                bool result;
     712
     713                Unify_new(
     714                        const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
     715                        ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
     716                        const ast::SymbolTable & symtab )
     717                : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
     718                  symtab(symtab), result(false) {}
     719
     720                void previsit( const ast::Node * ) { visit_children = false; }
     721               
     722                void postvisit( const ast::VoidType * ) {
     723                        result = dynamic_cast< const ast::VoidType * >( type2 );
     724                }
     725
     726                void postvisit( const ast::BasicType * basic ) {
     727                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
     728                                result = basic->kind == basic2->kind;
     729                        }
     730                }
     731
     732                void postvisit( const ast::PointerType * pointer ) {
     733                        if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
     734                                result = unifyExact(
     735                                        pointer->base, pointer2->base, tenv, need, have, open,
     736                                        noWiden(), symtab );
     737                        }
     738                }
     739
     740                void postvisit( const ast::ArrayType * array ) {
     741                        auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );
     742                        if ( ! array2 ) return;
     743
     744                        // to unify, array types must both be VLA or both not VLA and both must have a
     745                        // dimension expression or not have a dimension
     746                        if ( array->isVarLen != array2->isVarLen ) return;
     747                        if ( ! array->isVarLen && ! array2->isVarLen
     748                                        && array->dimension && array2->dimension ) {
     749                                auto ce1 = array->dimension.as< ast::ConstantExpr >();
     750                                auto ce2 = array2->dimension.as< ast::ConstantExpr >();
     751
     752                                // see C11 Reference Manual 6.7.6.2.6
     753                                // two array types with size specifiers that are integer constant expressions are
     754                                // compatible if both size specifiers have the same constant value
     755                                if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return;
     756                        }
     757
     758                        result = unifyExact(
     759                                array->base, array2->base, tenv, need, have, open, noWiden(),
     760                                symtab );
     761                }
     762
     763                void postvisit( const ast::ReferenceType * ref ) {
     764                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
     765                                result = unifyExact(
     766                                        ref->base, ref2->base, tenv, need, have, open, noWiden(),
     767                                        symtab );
     768                        }
     769                }
     770
     771        private:
     772                /// Replaces ttype variables with their bound types.
     773                /// If this isn't done when satifying ttype assertions, then argument lists can have
     774                /// different size and structure when they should be compatible.
     775                struct TtypeExpander_new : public ast::WithShortCircuiting {
     776                        ast::TypeEnvironment & tenv;
     777
     778                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
     779
     780                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     781                                if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     782                                        // expand ttype parameter into its actual type
     783                                        if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) {
     784                                                return clz->bound;
     785                                        }
     786                                }
     787                                return typeInst;
     788                        }
     789                };
     790
     791                /// returns flattened version of `src`
     792                static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
     793                        const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     794                ) {
     795                        std::vector< ast::ptr< ast::DeclWithType > > dst;
     796                        dst.reserve( src.size() );
     797                        for ( const ast::DeclWithType * d : src ) {
     798                                ast::Pass<TtypeExpander_new> expander{ env };
     799                                d = d->accept( expander );
     800                                auto types = flatten( d->get_type() );
     801                                for ( ast::ptr< ast::Type > & t : types ) {
     802                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     803                                        // a role in the unification of function types, since they do not determine
     804                                        // whether a function is callable.
     805                                        // NOTE: **must** consider at least mutex qualifier, since functions can be
     806                                        // overloaded on outermost mutex and a mutex function has different
     807                                        // requirements than a non-mutex function
     808                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
     809                                        dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
     810                                }
     811                        }
     812                        return dst;
     813                }
     814
     815                /// Creates a tuple type based on a list of DeclWithType
     816                template< typename Iter >
     817                static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     818                        std::vector< ast::ptr< ast::Type > > types;
     819                        while ( crnt != end ) {
     820                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     821                                // that this results in a flat tuple
     822                                flatten( (*crnt)->get_type(), types );
     823
     824                                ++crnt;
     825                        }
     826
     827                        return { new ast::TupleType{ std::move(types) } };
     828                }
     829
     830                template< typename Iter >
     831                static bool unifyDeclList(
     832                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
     833                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     834                        const ast::SymbolTable & symtab
     835                ) {
     836                        while ( crnt1 != end1 && crnt2 != end2 ) {
     837                                const ast::Type * t1 = (*crnt1)->get_type();
     838                                const ast::Type * t2 = (*crnt2)->get_type();
     839                                bool isTuple1 = Tuples::isTtype( t1 );
     840                                bool isTuple2 = Tuples::isTtype( t2 );
     841
     842                                // assumes here that ttype *must* be last parameter
     843                                if ( isTuple1 && ! isTuple2 ) {
     844                                        // combine remainder of list2, then unify
     845                                        return unifyExact(
     846                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     847                                                noWiden(), symtab );
     848                                } else if ( ! isTuple1 && isTuple2 ) {
     849                                        // combine remainder of list1, then unify
     850                                        return unifyExact(
     851                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     852                                                noWiden(), symtab );
     853                                }
     854
     855                                if ( ! unifyExact(
     856                                        t1, t2, env, need, have, open, noWiden(), symtab )
     857                                ) return false;
     858
     859                                ++crnt1; ++crnt2;
     860                        }
     861
     862                        // May get to the end of one argument list before the other. This is only okay if the
     863                        // other is a ttype
     864                        if ( crnt1 != end1 ) {
     865                                // try unifying empty tuple with ttype
     866                                const ast::Type * t1 = (*crnt1)->get_type();
     867                                if ( ! Tuples::isTtype( t1 ) ) return false;
     868                                return unifyExact(
     869                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     870                                        noWiden(), symtab );
     871                        } else if ( crnt2 != end2 ) {
     872                                // try unifying empty tuple with ttype
     873                                const ast::Type * t2 = (*crnt2)->get_type();
     874                                if ( ! Tuples::isTtype( t2 ) ) return false;
     875                                return unifyExact(
     876                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     877                                        noWiden(), symtab );
     878                        }
     879
     880                        return true;
     881                }
     882
     883                static bool unifyDeclList(
     884                        const std::vector< ast::ptr< ast::DeclWithType > > & list1,
     885                        const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     886                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     887                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
     888                ) {
     889                        return unifyDeclList(
     890                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
     891                                symtab );
     892                }
     893
     894                static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
     895                        auto i = assns.find( assn );
     896                        if ( i != assns.end() ) {
     897                                i->second.isUsed = true;
     898                        }
     899                }
     900
     901                /// mark all assertions in `type` used in both `assn1` and `assn2`
     902                static void markAssertions(
     903                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
     904                        const ast::ParameterizedType * type
     905                ) {
     906                        for ( const auto & tyvar : type->forall ) {
     907                                for ( const ast::DeclWithType * assert : tyvar->assertions ) {
     908                                        markAssertionSet( assn1, assert );
     909                                        markAssertionSet( assn2, assert );
     910                                }
     911                        }
     912                }
     913
     914        public:
     915                void postvisit( const ast::FunctionType * func ) {
     916                        auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );
     917                        if ( ! func2 ) return;
     918
     919                        if ( func->isVarArgs != func2->isVarArgs ) return;
     920                       
     921                        // Flatten the parameter lists for both functions so that tuple structure does not
     922                        // affect unification. Does not actually mutate function parameters.
     923                        auto params = flattenList( func->params, tenv );
     924                        auto params2 = flattenList( func2->params, tenv );
     925
     926                        // sizes don't have to match if ttypes are involved; need to be more precise w.r.t.
     927                        // where the ttype is to prevent errors
     928                        if (
     929                                ( params.size() != params2.size() || func->returns.size() != func2->returns.size() )
     930                                && ! func->isTtype()
     931                                && ! func2->isTtype()
     932                        ) return;
     933
     934                        if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
     935                        if ( ! unifyDeclList(
     936                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
     937                       
     938                        markAssertions( have, need, func );
     939                        markAssertions( have, need, func2 );
     940
     941                        result = true;
     942                }
     943       
     944        private:
     945                template< typename RefType >
     946                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     947                        // check that the other type is compatible and named the same
     948                        auto otherInst = dynamic_cast< const RefType * >( other );
     949                        result = otherInst && inst->name == otherInst->name;
     950                        return otherInst;
     951                }
     952
     953                /// Creates a tuple type based on a list of TypeExpr
     954                template< typename Iter >
     955                static const ast::Type * tupleFromExprs(
     956                        const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs
     957                ) {
     958                        std::vector< ast::ptr< ast::Type > > types;
     959                        do {
     960                                types.emplace_back( param->type );
     961
     962                                ++crnt;
     963                                if ( crnt == end ) break;
     964                                param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() );
     965                        } while(true);
     966
     967                        return new ast::TupleType{ std::move(types), qs };
     968                }
     969
     970                template< typename RefType >
     971                void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     972                        // check that other type is compatible and named the same
     973                        const RefType * inst2 = handleRefType( inst, other );
     974                        if ( ! inst2 ) return;
     975                       
     976                        // check that parameters of types unify, if any
     977                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
     978                        const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     979
     980                        auto it = params.begin();
     981                        auto jt = params2.begin();
     982                        for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) {
     983                                auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() );
     984                                auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() );
     985
     986                                ast::ptr< ast::Type > pty = param->type;
     987                                ast::ptr< ast::Type > pty2 = param2->type;
     988
     989                                bool isTuple = Tuples::isTtype( pty );
     990                                bool isTuple2 = Tuples::isTtype( pty2 );
     991
     992                                if ( isTuple && isTuple2 ) {
     993                                        ++it; ++jt;  // skip ttype parameters before break
     994                                } else if ( isTuple ) {
     995                                        // bundle remaining params into tuple
     996                                        pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers );
     997                                        ++it;  // skip ttype parameter for break
     998                                } else if ( isTuple2 ) {
     999                                        // bundle remaining params into tuple
     1000                                        pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers );
     1001                                        ++jt;  // skip ttype parameter for break
     1002                                }
     1003
     1004                                if ( ! unifyExact(
     1005                                                pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
     1006                                        result = false;
     1007                                        return;
     1008                                }
     1009
     1010                                // ttype parameter should be last
     1011                                if ( isTuple || isTuple2 ) break;
     1012                        }
     1013                        result = it == params.end() && jt == params2.end();
     1014                }
     1015
     1016        public:
     1017                void postvisit( const ast::StructInstType * aggrType ) {
     1018                        handleGenericRefType( aggrType, type2 );
     1019                }
     1020
     1021                void postvisit( const ast::UnionInstType * aggrType ) {
     1022                        handleGenericRefType( aggrType, type2 );
     1023                }
     1024
     1025                void postvisit( const ast::EnumInstType * aggrType ) {
     1026                        handleRefType( aggrType, type2 );
     1027                }
     1028
     1029                void postvisit( const ast::TraitInstType * aggrType ) {
     1030                        handleRefType( aggrType, type2 );
     1031                }
     1032
     1033                void postvisit( const ast::TypeInstType * typeInst ) {
     1034                        assert( open.find( typeInst->name ) == open.end() );
     1035                        handleRefType( typeInst, type2 );
     1036                }
     1037
     1038        private:
     1039                /// Creates a tuple type based on a list of Type
     1040                static ast::ptr< ast::Type > tupleFromTypes(
     1041                        const std::vector< ast::ptr< ast::Type > > & tys
     1042                ) {
     1043                        std::vector< ast::ptr< ast::Type > > out;
     1044                        for ( const ast::Type * ty : tys ) {
     1045                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     1046                                // that this results in a flat tuple
     1047                                flatten( ty, out );
     1048                        }
     1049
     1050                        return { new ast::TupleType{ std::move(out) } };
     1051                }
     1052
     1053                static bool unifyList(
     1054                        const std::vector< ast::ptr< ast::Type > > & list1,
     1055                        const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
     1056                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1057                        const ast::SymbolTable & symtab
     1058                ) {
     1059                        auto crnt1 = list1.begin();
     1060                        auto crnt2 = list2.begin();
     1061                        while ( crnt1 != list1.end() && crnt2 != list2.end() ) {
     1062                                const ast::Type * t1 = *crnt1;
     1063                                const ast::Type * t2 = *crnt2;
     1064                                bool isTuple1 = Tuples::isTtype( t1 );
     1065                                bool isTuple2 = Tuples::isTtype( t2 );
     1066
     1067                                // assumes ttype must be last parameter
     1068                                if ( isTuple1 && ! isTuple2 ) {
     1069                                        // combine entirety of list2, then unify
     1070                                        return unifyExact(
     1071                                                t1, tupleFromTypes( list2 ), env, need, have, open,
     1072                                                noWiden(), symtab );
     1073                                } else if ( ! isTuple1 && isTuple2 ) {
     1074                                        // combine entirety of list1, then unify
     1075                                        return unifyExact(
     1076                                                tupleFromTypes( list1 ), t2, env, need, have, open,
     1077                                                noWiden(), symtab );
     1078                                }
     1079
     1080                                if ( ! unifyExact(
     1081                                        t1, t2, env, need, have, open, noWiden(), symtab )
     1082                                ) return false;
     1083
     1084                                ++crnt1; ++crnt2;
     1085                        }
     1086
     1087                        if ( crnt1 != list1.end() ) {
     1088                                // try unifying empty tuple type with ttype
     1089                                const ast::Type * t1 = *crnt1;
     1090                                if ( ! Tuples::isTtype( t1 ) ) return false;
     1091                                // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
     1092                                // from Rob's code
     1093                                return unifyExact(
     1094                                                t1, tupleFromTypes( list2 ), env, need, have, open,
     1095                                                noWiden(), symtab );
     1096                        } else if ( crnt2 != list2.end() ) {
     1097                                // try unifying empty tuple with ttype
     1098                                const ast::Type * t2 = *crnt2;
     1099                                if ( ! Tuples::isTtype( t2 ) ) return false;
     1100                                // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
     1101                                // from Rob's code
     1102                                return unifyExact(
     1103                                                tupleFromTypes( list1 ), t2, env, need, have, open,
     1104                                                noWiden(), symtab );
     1105                        }
     1106
     1107                        return true;
     1108                }
     1109
     1110        public:
     1111                void postvisit( const ast::TupleType * tuple ) {
     1112                        auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );
     1113                        if ( ! tuple2 ) return;
     1114
     1115                        ast::Pass<TtypeExpander_new> expander{ tenv };
     1116                        const ast::Type * flat = tuple->accept( expander );
     1117                        const ast::Type * flat2 = tuple2->accept( expander );
     1118
     1119                        auto types = flatten( flat );
     1120                        auto types2 = flatten( flat2 );
     1121
     1122                        result = unifyList( types, types2, tenv, need, have, open, symtab );
     1123                }
     1124
     1125                void postvisit( const ast::VarArgsType * ) {
     1126                        result = dynamic_cast< const ast::VarArgsType * >( type2 );
     1127                }
     1128
     1129                void postvisit( const ast::ZeroType * ) {
     1130                        result = dynamic_cast< const ast::ZeroType * >( type2 );
     1131                }
     1132
     1133                void postvisit( const ast::OneType * ) {
     1134                        result = dynamic_cast< const ast::OneType * >( type2 );
     1135                }       
     1136
     1137          private:
     1138                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     1139                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
     1140        };
     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        }
     1153
     1154        bool unifyExact(
     1155                        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     1156                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1157                        WidenMode widen, const ast::SymbolTable & symtab
     1158        ) {
     1159                if ( type1->qualifiers != type2->qualifiers ) return false;
     1160
     1161                auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 );
     1162                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
     1163                ast::OpenVarSet::const_iterator
     1164                        entry1 = var1 ? open.find( var1->name ) : open.end(),
     1165                        entry2 = var2 ? open.find( var2->name ) : open.end();
     1166                bool isopen1 = entry1 != open.end();
     1167                bool isopen2 = entry2 != open.end();
     1168
     1169                if ( isopen1 && isopen2 ) {
     1170                        if ( entry1->second.kind != entry2->second.kind ) return false;
     1171                        return env.bindVarToVar(
     1172                                var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have,
     1173                                open, widen, symtab );
     1174                } else if ( isopen1 ) {
     1175                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
     1176                } else if ( isopen2 ) {
     1177                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     1178                } else {
     1179                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
     1180                        type1->accept( comparator );
     1181                        return comparator.pass.result;
     1182                }
     1183        }
     1184
     1185        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
     1190        ) {
     1191                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     1192               
     1193                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
     1194                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
     1195                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
     1196                reset_qualifiers( t1 );
     1197                reset_qualifiers( t2 );
     1198               
     1199                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1200                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1201
     1202                        // if exact unification on unqualified types, try to merge qualifiers
     1203                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
     1204                                common = type1;
     1205                                reset_qualifiers( common, q1 | q2 );
     1206                                return true;
     1207                        } else {
     1208                                return false;
     1209                        }
     1210
     1211                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1212                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1213
     1214                        // no exact unification, but common type
     1215                        reset_qualifiers( common, q1 | q2 );
     1216                        return true;
     1217                } else {
     1218                        return false;
     1219                }
     1220        }
     1221
    6491222        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    6501223                if ( func->returns.empty() ) return new ast::VoidType{};
  • src/ResolvExpr/Unify.h

    r7564e10 r67130fe  
    1818#include <list>                   // for list
    1919
     20#include "AST/Node.hpp"             // for ptr
     21#include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    2022#include "Common/utility.h"       // for deleteAll
    2123#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2224#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    23 #include "WidenMode.h"            // for WidenMode
     25#include "WidenMode.h"              // for WidenMode
    2426
    2527class Type;
    2628class TypeInstType;
    2729namespace SymTab {
    28 class Indexer;
    29 }  // namespace SymTab
     30        class Indexer;
     31}
     32
     33namespace ast {
     34        class SymbolTable;
     35        class Type;
     36}
    3037
    3138namespace ResolvExpr {
     
    3340        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    3441        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    35         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
     42        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    3643
    3744        template< typename Iterator1, typename Iterator2 >
     
    6269        }
    6370
     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
     76        bool unifyExact(
     77                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 );
     80
     81        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 );
     86
    6487} // namespace ResolvExpr
    6588
  • src/ResolvExpr/WidenMode.h

    r7564e10 r67130fe  
    1818namespace ResolvExpr {
    1919        struct WidenMode {
    20                 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
    21                 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
    22                 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
    23                 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
    24                 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
    25                 operator bool() { return widenFirst && widenSecond; }
     20                WidenMode( bool first, bool second ): first( first ), second( second ) {}
     21               
     22                WidenMode &operator|=( const WidenMode &other ) {
     23                        first |= other.first; second |= other.second; return *this;
     24                }
    2625
    27                 bool widenFirst : 1, widenSecond : 1;
     26                WidenMode &operator&=( const WidenMode &other ) {
     27                        first &= other.first; second &= other.second; return *this;
     28                }
     29
     30                WidenMode operator|( const WidenMode &other ) {
     31                        WidenMode newWM( *this ); newWM |= other; return newWM;
     32                }
     33
     34                WidenMode operator&( const WidenMode &other ) {
     35                        WidenMode newWM( *this ); newWM &= other; return newWM;
     36                }
     37               
     38                operator bool() { return first && second; }
     39
     40                bool first : 1, second : 1;
    2841        };
     42
     43        static inline WidenMode noWiden() { return { false, false }; }
    2944} // namespace ResolvExpr
    3045
  • src/ResolvExpr/typeops.h

    r7564e10 r67130fe  
    1818#include <vector>
    1919
     20#include "Cost.h"
     21#include "TypeEnvironment.h"
     22#include "WidenMode.h"
     23#include "AST/Fwd.hpp"
    2024#include "AST/Node.hpp"
     25#include "AST/SymbolTable.hpp"
    2126#include "AST/Type.hpp"
     27#include "AST/TypeEnvironment.hpp"
    2228#include "SynTree/SynTree.h"
    2329#include "SynTree/Type.h"
    2430#include "SymTab/Indexer.h"
    25 #include "Cost.h"
    26 #include "TypeEnvironment.h"
    2731
    2832namespace ResolvExpr {
     
    8589
    8690        // in Unify.cc
    87         bool isFtype( Type *type );
    8891        bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    8992        bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    99102        }
    100103
     104        bool typesCompatible(
     105                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     106                const ast::TypeEnvironment & env = {} );
     107       
     108        bool typesCompatibleIgnoreQualifiers(
     109                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     110                const ast::TypeEnvironment & env = {} );
     111
    101112        /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
    102113        Type * extractResultType( FunctionType * functionType );
     
    106117        // in CommonType.cc
    107118        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,
     121                const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
    108122
    109123        // in PolyCost.cc
     
    115129        // in Occurs.cc
    116130        bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
     131        // new AST version in TypeEnvironment.cpp (only place it was used in old AST)
    117132
    118133        template<typename Iter>
     
    127142        // in AlternativeFinder.cc
    128143        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
     144        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
    129145
    130         // flatten tuple type into list of types
     146        /// flatten tuple type into list of types
    131147        template< typename OutputIterator >
    132148        void flatten( Type * type, OutputIterator out ) {
     
    139155                }
    140156        }
     157
     158        /// flatten tuple type into existing list of types
     159        static inline void flatten(
     160                const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
     161        ) {
     162                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {       
     163                        for ( const ast::Type * t : tupleType->types ) {
     164                                flatten( t, out );
     165                        }
     166                } else {
     167                        out.emplace_back( type );
     168                }
     169        }
     170
     171        /// flatten tuple type into list of types
     172        static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
     173                std::vector< ast::ptr< ast::Type > > out;
     174                out.reserve( type->size() );
     175                flatten( type, out );
     176                return out;
     177        }
     178
     179        // in TypeEnvironment.cc
     180        bool isFtype( Type *type );
    141181} // namespace ResolvExpr
     182
     183namespace ast {
     184        // in TypeEnvironment.cpp
     185        bool isFtype( const ast::Type * type );
     186} // namespace ast
    142187
    143188// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.