Changeset 21300d7 for src/ResolvExpr


Ignore:
Timestamp:
Jun 12, 2019, 4:06:37 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
462a7c7, d60780c
Parents:
aaeacf4 (diff), 6625727 (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:
4 added
17 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AdjustExprType.cc

    raaeacf4 r21300d7  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AdjustExprType.cc --
     7// AdjustExprType_old.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1414//
    1515
     16#include "AST/Node.hpp"
     17#include "AST/Pass.hpp"
     18#include "AST/SymbolTable.hpp"
     19#include "AST/Type.hpp"
     20#include "AST/TypeEnvironment.hpp"
    1621#include "Common/PassVisitor.h"
    1722#include "SymTab/Indexer.h"       // for Indexer
     
    2227
    2328namespace ResolvExpr {
    24         class AdjustExprType : public WithShortCircuiting {
    25           public:
    26                 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer );
     29
     30namespace {
     31        class AdjustExprType_old final : public WithShortCircuiting {
     32                public:
     33                AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    2734                void premutate( VoidType * ) { visit_children = false; }
    2835                void premutate( BasicType * ) { visit_children = false; }
     
    4451                Type * postmutate( TypeInstType *aggregateUseType );
    4552
    46           private:
     53                private:
    4754                const TypeEnvironment & env;
    4855                const SymTab::Indexer & indexer;
    4956        };
    5057
    51         void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    52                 PassVisitor<AdjustExprType> adjuster( env, indexer );
    53                 Type *newType = type->acceptMutator( adjuster );
    54                 type = newType;
    55         }
    56 
    57         void adjustExprType( Type *& type ) {
    58                 TypeEnvironment env;
    59                 SymTab::Indexer indexer;
    60                 adjustExprType( type, env, indexer );
    61         }
    62 
    63         AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer )
     58        AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    6459                : env( env ), indexer( indexer ) {
    6560        }
    6661
    67         Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
     62        Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
    6863                PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    6964                arrayType->base = nullptr;
     
    7267        }
    7368
    74         Type * AdjustExprType::postmutate( FunctionType * functionType ) {
     69        Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
    7570                return new PointerType{ Type::Qualifiers(), functionType };
    7671        }
    7772
    78         Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
     73        Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
    7974                if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
    8075                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
     
    9085                return typeInst;
    9186        }
     87} // anonymous namespace
     88
     89void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     90        PassVisitor<AdjustExprType_old> adjuster( env, indexer );
     91        Type *newType = type->acceptMutator( adjuster );
     92        type = newType;
     93}
     94
     95void adjustExprType( Type *& type ) {
     96        TypeEnvironment env;
     97        SymTab::Indexer indexer;
     98        adjustExprType( type, env, indexer );
     99}
     100
     101namespace {
     102        struct AdjustExprType_new final : public ast::WithShortCircuiting {
     103                const ast::TypeEnvironment & tenv;
     104                const ast::SymbolTable & symtab;
     105
     106                AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
     107                : tenv( e ), symtab( syms ) {}
     108
     109                void premutate( const ast::VoidType * ) { visit_children = false; }
     110                void premutate( const ast::BasicType * ) { visit_children = false; }
     111                void premutate( const ast::PointerType * ) { visit_children = false; }
     112                void premutate( const ast::ArrayType * ) { visit_children = false; }
     113                void premutate( const ast::FunctionType * ) { visit_children = false; }
     114                void premutate( const ast::StructInstType * ) { visit_children = false; }
     115                void premutate( const ast::UnionInstType * ) { visit_children = false; }
     116                void premutate( const ast::EnumInstType * ) { visit_children = false; }
     117                void premutate( const ast::TraitInstType * ) { visit_children = false; }
     118                void premutate( const ast::TypeInstType * ) { visit_children = false; }
     119                void premutate( const ast::TupleType * ) { visit_children = false; }
     120                void premutate( const ast::VarArgsType * ) { visit_children = false; }
     121                void premutate( const ast::ZeroType * ) { visit_children = false; }
     122                void premutate( const ast::OneType * ) { visit_children = false; }
     123
     124                const ast::Type * postmutate( const ast::ArrayType * at ) {
     125                        return new ast::PointerType{ at->base, at->qualifiers };
     126                }
     127
     128                const ast::Type * postmutate( const ast::FunctionType * ft ) {
     129                        return new ast::PointerType{ ft };
     130                }
     131
     132                const ast::Type * postmutate( const ast::TypeInstType * inst ) {
     133                        // replace known function-type-variables with pointer-to-function
     134                        if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
     135                                if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
     136                                        return new ast::PointerType{ inst };
     137                                }
     138                        } else if ( const ast::NamedTypeDecl * ntDecl = symtab.lookupType( inst->name ) ) {
     139                                if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( ntDecl ) ) {
     140                                        if ( tyDecl->kind == ast::TypeVar::Ftype ) {
     141                                                return new ast::PointerType{ inst };
     142                                        }
     143                                }
     144                        }
     145                        return inst;
     146                }
     147        };
     148} // anonymous namespace
     149
     150const ast::Type * adjustExprType(
     151        const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
     152) {
     153        ast::Pass<AdjustExprType_new> adjuster{ env, symtab };
     154        return type->accept( adjuster );
     155}
     156
    92157} // namespace ResolvExpr
    93158
  • src/ResolvExpr/AlternativeFinder.cc

    raaeacf4 r21300d7  
    2929#include "AlternativeFinder.h"
    3030#include "AST/Expr.hpp"
     31#include "AST/SymbolTable.hpp"
    3132#include "AST/Type.hpp"
    3233#include "Common/SemanticError.h"  // for SemanticError
     
    115116                /// Finds matching alternatives for a function, given a set of arguments
    116117                template<typename OutputIterator>
    117                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
     118                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out );
    118119                /// Sets up parameter inference for an output alternative
    119120                template< typename OutputIterator >
     
    266267                        SemanticError( expr, "No reasonable alternatives for expression " );
    267268                }
    268                 if ( mode.resolveAssns || mode.prune ) {
     269                if ( mode.satisfyAssns || mode.prune ) {
    269270                        // trim candidates just to those where the assertions resolve
    270271                        // - necessary pre-requisite to pruning
     
    592593
    593594                /// Gets the list of exploded alternatives for this pack
    594                 const ExplodedActual& getExpl( const ExplodedArgs& args ) const {
     595                const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
    595596                        return args[nextArg-1][explAlt];
    596597                }
     
    616617        /// Instantiates an argument to match a formal, returns false if no results left
    617618        bool instantiateArgument( Type* formalType, Initializer* initializer,
    618                         const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
     619                        const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
    619620                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    620621                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    888889        template<typename OutputIterator>
    889890        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    890                         FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
     891                        FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
    891892                OpenVarSet funcOpenVars;
    892893                AssertionSet funcNeed, funcHave;
     
    10201021
    10211022                // pre-explode arguments
    1022                 ExplodedArgs argExpansions;
     1023                ExplodedArgs_old argExpansions;
    10231024                argExpansions.reserve( argAlternatives.size() );
    10241025
  • src/ResolvExpr/AlternativeFinder.h

    raaeacf4 r21300d7  
    3737        /// First index is which argument, second index is which alternative for that argument,
    3838        /// third index is which exploded element of that alternative
    39         using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;
     39        using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >;
    4040
    4141        class AlternativeFinder {
  • src/ResolvExpr/Candidate.hpp

    raaeacf4 r21300d7  
    3030        /// A list of unresolved assertions
    3131        using AssertionList = std::vector<AssertionSet::value_type>;
     32
     33        /// Convenience to merge AssertionList into AssertionSet
     34        static inline void mergeAssertionSet( AssertionSet & dst, const AssertionList & src ) {
     35                for ( const auto & s : src ) { dst.emplace( s ); }
     36        }
    3237}
    3338
     
    4247        ast::OpenVarSet open;      ///< Open variables for environment
    4348        ast::AssertionList need;   ///< Assertions which need to be resolved
     49
     50        Candidate() : expr(), cost( Cost::zero ), cvtCost( Cost::zero ), env(), open(), need() {}
     51       
     52        Candidate( const ast::Expr * x, const ast::TypeEnvironment & e )
     53        : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {}
     54
     55        Candidate( const Candidate & o, const ast::Expr * x )
     56        : expr( x ), cost( o.cost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ),
     57          need( o.need ) {}
     58       
     59        Candidate(
     60                const ast::Expr * x, ast::TypeEnvironment && e, ast::OpenVarSet && o,
     61                ast::AssertionSet && n, const Cost & c )
     62        : expr( x ), cost( c ), cvtCost( Cost::zero ), env( std::move( e ) ), open( std::move( o ) ),
     63          need( n.begin(), n.end() ) {}
    4464};
    4565
     
    4969/// List of candidates
    5070using CandidateList = std::vector< CandidateRef >;
     71
     72/// Splice src after dst, clearing src
     73static inline void splice( CandidateList & dst, CandidateList & src ) {
     74        dst.reserve( dst.size() + src.size() );
     75        for ( CandidateRef & r : src ) { dst.emplace_back( std::move( r ) ); }
     76        src.clear();
     77}
     78
     79/// Splice src before dst
     80static inline void spliceBegin( CandidateList & dst, CandidateList & src ) {
     81        splice( src, dst );
     82        dst.swap( src );
     83}
     84
     85/// Sum the cost of a list of candidates
     86static inline Cost sumCost( const CandidateList & candidates ) {
     87        Cost total = Cost::zero;
     88        for ( const CandidateRef & r : candidates ) { total += r->cost; }
     89        return total;
     90}
     91
     92/// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated?
     93static inline void promoteCvtCost( CandidateList & candidates ) {
     94        for ( CandidateRef & r : candidates ) {
     95                r->cost = r->cvtCost;
     96        }
     97}
    5198
    5299void print( std::ostream & os, const Candidate & cand, Indenter indent = {} );
  • src/ResolvExpr/CandidateFinder.cpp

    raaeacf4 r21300d7  
    1616#include "CandidateFinder.hpp"
    1717
     18#include <deque>
     19#include <iterator>               // for back_inserter
     20#include <sstream>
     21#include <string>
     22#include <unordered_map>
     23#include <vector>
     24
     25#include "Candidate.hpp"
     26#include "CompilationState.h"
     27#include "Cost.h"
     28#include "ExplodedArg.hpp"
     29#include "Resolver.h"
     30#include "SatisfyAssertions.hpp"
     31#include "typeops.h"              // for adjustExprType
     32#include "Unify.h"
    1833#include "AST/Expr.hpp"
     34#include "AST/Node.hpp"
     35#include "AST/Pass.hpp"
     36#include "AST/Print.hpp"
     37#include "AST/SymbolTable.hpp"
     38#include "AST/Type.hpp"
     39#include "SymTab/Mangler.h"
     40#include "Tuples/Tuples.h"        // for handleTupleAssignment
     41
     42#define PRINT( text ) if ( resolvep ) { text }
    1943
    2044namespace ResolvExpr {
    2145
     46namespace {
     47
     48        /// First index is which argument, second is which alternative, third is which exploded element
     49        using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;
     50
     51        /// Returns a list of alternatives with the minimum cost in the given list
     52        CandidateList findMinCost( const CandidateList & candidates ) {
     53                CandidateList out;
     54                Cost minCost = Cost::infinity;
     55                for ( const CandidateRef & r : candidates ) {
     56                        if ( r->cost < minCost ) {
     57                                minCost = r->cost;
     58                                out.clear();
     59                                out.emplace_back( r );
     60                        } else if ( r->cost == minCost ) {
     61                                out.emplace_back( r );
     62                        }
     63                }
     64                return out;
     65        }
     66
     67        /// Computes conversion cost for a given candidate
     68        Cost computeApplicationConversionCost(
     69                const CandidateRef & cand, const ast::SymbolTable & symtab
     70        ) {
     71                #warning unimplemented
     72                (void)cand; (void)symtab;
     73                assert(false);
     74                return Cost::infinity;
     75        }
     76
     77        /// Actually visits expressions to find their candidate interpretations
     78        struct Finder final : public ast::WithShortCircuiting {
     79                CandidateFinder & selfFinder;
     80                const ast::SymbolTable & symtab;
     81                CandidateList & candidates;
     82                const ast::TypeEnvironment & tenv;
     83                ast::ptr< ast::Type > & targetType;
     84
     85                Finder( CandidateFinder & f )
     86                : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     87                  targetType( f.targetType ) {}
     88               
     89                void previsit( const ast::Node * ) { visit_children = false; }
     90
     91                /// Convenience to add candidate to list
     92                template<typename... Args>
     93                void addCandidate( Args &&... args ) {
     94                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     95                }
     96
     97                void postvisit( const ast::ApplicationExpr * applicationExpr ) {
     98                        addCandidate( applicationExpr, tenv );
     99                }
     100
     101                /// Builds a list of candidates for a function, storing them in out
     102                void makeFunctionCandidates(
     103                        const CandidateRef & func, const ast::FunctionType * funcType,
     104                        const ExplodedArgs_new & args, CandidateList & out
     105                ) {
     106                        #warning unimplemented
     107                        (void)func; (void)funcType; (void)args; (void)out;
     108                        assert(false);
     109                }
     110
     111                /// Adds implicit struct-conversions to the alternative list
     112                void addAnonConversions( const CandidateRef & cand ) {
     113                        #warning unimplemented
     114                        (void)cand;
     115                        assert(false);
     116                }
     117
     118                void postvisit( const ast::UntypedExpr * untypedExpr ) {
     119                        CandidateFinder funcFinder{ symtab, tenv };
     120                        funcFinder.find( untypedExpr->func, ResolvMode::withAdjustment() );
     121                        // short-circuit if no candidates
     122                        if ( funcFinder.candidates.empty() ) return;
     123
     124                        std::vector< CandidateFinder > argCandidates =
     125                                selfFinder.findSubExprs( untypedExpr->args );
     126                       
     127                        // take care of possible tuple assignments
     128                        // if not tuple assignment, handled as normal function call
     129                        Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
     130
     131                        // find function operators
     132                        ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
     133                        CandidateFinder opFinder{ symtab, tenv };
     134                        // okay if there aren't any function operations
     135                        opFinder.find( opExpr, ResolvMode::withoutFailFast() );
     136                        PRINT(
     137                                std::cerr << "known function ops:" << std::endl;
     138                                print( std::cerr, opFinder.candidates, 1 );
     139                        )
     140
     141                        // pre-explode arguments
     142                        ExplodedArgs_new argExpansions;
     143                        for ( const CandidateFinder & args : argCandidates ) {
     144                                argExpansions.emplace_back();
     145                                auto & argE = argExpansions.back();
     146                                for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }
     147                        }
     148
     149                        // Find function matches
     150                        CandidateList found;
     151                        SemanticErrorException errors;
     152                        for ( CandidateRef & func : funcFinder ) {
     153                                try {
     154                                        PRINT(
     155                                                std::cerr << "working on alternative:" << std::endl;
     156                                                print( std::cerr, *func, 2 );
     157                                        )
     158
     159                                        // check if the type is a pointer to function
     160                                        const ast::Type * funcResult = func->expr->result->stripReferences();
     161                                        if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {
     162                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
     163                                                        CandidateRef newFunc{ new Candidate{ *func } };
     164                                                        newFunc->expr =
     165                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
     166                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
     167                                                }
     168                                        } else if (
     169                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
     170                                        ) {
     171                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
     172                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
     173                                                                CandidateRef newFunc{ new Candidate{ *func } };
     174                                                                newFunc->expr =
     175                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
     176                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     177                                                        }
     178                                                }
     179                                        }
     180                                } catch ( SemanticErrorException & e ) { errors.append( e ); }
     181                        }
     182
     183                        // Find matches on function operators `?()`
     184                        if ( ! opFinder.candidates.empty() ) {
     185                                // add exploded function alternatives to front of argument list
     186                                std::vector< ExplodedArg > funcE;
     187                                funcE.reserve( funcFinder.candidates.size() );
     188                                for ( const CandidateRef & func : funcFinder ) {
     189                                        funcE.emplace_back( *func, symtab );
     190                                }
     191                                argExpansions.emplace_front( std::move( funcE ) );
     192
     193                                for ( const CandidateRef & op : opFinder ) {
     194                                        try {
     195                                                // check if type is pointer-to-function
     196                                                const ast::Type * opResult = op->expr->result->stripReferences();
     197                                                if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {
     198                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
     199                                                                CandidateRef newOp{ new Candidate{ *op} };
     200                                                                newOp->expr =
     201                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
     202                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     203                                                        }
     204                                                }
     205                                        } catch ( SemanticErrorException & e ) { errors.append( e ); }
     206                                }
     207                        }
     208
     209                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
     210                        // candidates
     211                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     212
     213                        // Compute conversion costs
     214                        for ( CandidateRef & withFunc : found ) {
     215                                Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
     216
     217                                PRINT(
     218                                        auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
     219                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
     220                                        auto function = pointer->base.strict_as< ast::FunctionType >();
     221                                       
     222                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
     223                                        std::cerr << "parameters are:" << std::endl;
     224                                        ast::printAll( std::cerr, function->params, 2 );
     225                                        std::cerr << "arguments are:" << std::endl;
     226                                        ast::printAll( std::cerr, appExpr->args, 2 );
     227                                        std::cerr << "bindings are:" << std::endl;
     228                                        ast::print( std::cerr, withFunc->env, 2 );
     229                                        std::cerr << "cost is: " << withFunc->cost << std::endl;
     230                                        std::cerr << "cost of conversion is:" << cvtCost << std::endl;
     231                                )
     232
     233                                if ( cvtCost != Cost::infinity ) {
     234                                        withFunc->cvtCost = cvtCost;
     235                                        candidates.emplace_back( std::move( withFunc ) );
     236                                }
     237                        }
     238                        found = std::move( candidates );
     239
     240                        // use a new list so that candidates are not examined by addAnonConversions twice
     241                        CandidateList winners = findMinCost( found );
     242                        promoteCvtCost( winners );
     243
     244                        // function may return a struct/union value, in which case we need to add candidates
     245                        // for implicit conversions to each of the anonymous members, which must happen after
     246                        // `findMinCost`, since anon conversions are never the cheapest
     247                        for ( const CandidateRef & c : winners ) {
     248                                addAnonConversions( c );
     249                        }
     250                        spliceBegin( candidates, winners );
     251
     252                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
     253                                // If resolution is unsuccessful with a target type, try again without, since it
     254                                // will sometimes succeed when it wouldn't with a target type binding.
     255                                // For example:
     256                                //   forall( otype T ) T & ?[]( T *, ptrdiff_t );
     257                                //   const char * x = "hello world";
     258                                //   unsigned char ch = x[0];
     259                                // Fails with simple return type binding (xxx -- check this!) as follows:
     260                                // * T is bound to unsigned char
     261                                // * (x: const char *) is unified with unsigned char *, which fails
     262                                // xxx -- fix this better
     263                                targetType = nullptr;
     264                                postvisit( untypedExpr );
     265                        }
     266                }
     267
     268                /// true if expression is an lvalue
     269                static bool isLvalue( const ast::Expr * x ) {
     270                        return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     271                }
     272
     273                void postvisit( const ast::AddressExpr * addressExpr ) {
     274                        CandidateFinder finder{ symtab, tenv };
     275                        finder.find( addressExpr->arg );
     276                        for ( CandidateRef & r : finder.candidates ) {
     277                                if ( ! isLvalue( r->expr ) ) continue;
     278                                addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );
     279                        }
     280                }
     281
     282                void postvisit( const ast::LabelAddressExpr * labelExpr ) {
     283                        addCandidate( labelExpr, tenv );
     284                }
     285
     286                void postvisit( const ast::CastExpr * castExpr ) {
     287                        #warning unimplemented
     288                        (void)castExpr;
     289                        assert(false);
     290                }
     291
     292                void postvisit( const ast::VirtualCastExpr * castExpr ) {
     293                        assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
     294                        CandidateFinder finder{ symtab, tenv };
     295                        // don't prune here, all alternatives guaranteed to have same type
     296                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
     297                        for ( CandidateRef & r : finder.candidates ) {
     298                                addCandidate(
     299                                        *r, new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
     300                        }
     301                }
     302
     303                void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
     304                        #warning unimplemented
     305                        (void)memberExpr;
     306                        assert(false);
     307                }
     308
     309                void postvisit( const ast::MemberExpr * memberExpr ) {
     310                        addCandidate( memberExpr, tenv );
     311                }
     312
     313                void postvisit( const ast::NameExpr * variableExpr ) {
     314                        #warning unimplemented
     315                        (void)variableExpr;
     316                        assert(false);
     317                }
     318
     319                void postvisit( const ast::VariableExpr * variableExpr ) {
     320                        // not sufficient to just pass `variableExpr` here, type might have changed since
     321                        // creation
     322                        addCandidate(
     323                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
     324                }
     325
     326                void postvisit( const ast::ConstantExpr * constantExpr ) {
     327                        addCandidate( constantExpr, tenv );
     328                }
     329
     330                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
     331                        #warning unimplemented
     332                        (void)sizeofExpr;
     333                        assert(false);
     334                }
     335
     336                void postvisit( const ast::AlignofExpr * alignofExpr ) {
     337                        #warning unimplemented
     338                        (void)alignofExpr;
     339                        assert(false);
     340                }
     341
     342                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
     343                        #warning unimplemented
     344                        (void)offsetofExpr;
     345                        assert(false);
     346                }
     347
     348                void postvisit( const ast::OffsetofExpr * offsetofExpr ) {
     349                        addCandidate( offsetofExpr, tenv );
     350                }
     351
     352                void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {
     353                        addCandidate( offsetPackExpr, tenv );
     354                }
     355
     356                void postvisit( const ast::LogicalExpr * logicalExpr ) {
     357                        CandidateFinder finder1{ symtab, tenv };
     358                        finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
     359                        if ( finder1.candidates.empty() ) return;
     360
     361                        CandidateFinder finder2{ symtab, tenv };
     362                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
     363                        if ( finder2.candidates.empty() ) return;
     364
     365                        for ( const CandidateRef & r1 : finder1.candidates ) {
     366                                for ( const CandidateRef & r2 : finder2.candidates ) {
     367                                        ast::TypeEnvironment env{ r1->env };
     368                                        env.simpleCombine( r2->env );
     369                                        ast::OpenVarSet open{ r1->open };
     370                                        mergeOpenVars( open, r2->open );
     371                                        ast::AssertionSet need;
     372                                        mergeAssertionSet( need, r1->need );
     373                                        mergeAssertionSet( need, r2->need );
     374
     375                                        addCandidate(
     376                                                new ast::LogicalExpr{
     377                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
     378                                                std::move( env ), std::move( open ), std::move( need ),
     379                                                r1->cost + r2->cost );
     380                                }
     381                        }
     382                }
     383
     384                void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
     385                        // candidates for condition
     386                        CandidateFinder finder1{ symtab, tenv };
     387                        finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
     388                        if ( finder1.candidates.empty() ) return;
     389
     390                        // candidates for true result
     391                        CandidateFinder finder2{ symtab, tenv };
     392                        finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
     393                        if ( finder2.candidates.empty() ) return;
     394
     395                        // candidates for false result
     396                        CandidateFinder finder3{ symtab, tenv };
     397                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
     398                        if ( finder3.candidates.empty() ) return;
     399
     400                        for ( const CandidateRef & r1 : finder1.candidates ) {
     401                                for ( const CandidateRef & r2 : finder2.candidates ) {
     402                                        for ( const CandidateRef & r3 : finder3.candidates ) {
     403                                                ast::TypeEnvironment env{ r1->env };
     404                                                env.simpleCombine( r2->env );
     405                                                env.simpleCombine( r3->env );
     406                                                ast::OpenVarSet open{ r1->open };
     407                                                mergeOpenVars( open, r2->open );
     408                                                mergeOpenVars( open, r3->open );
     409                                                ast::AssertionSet need;
     410                                                mergeAssertionSet( need, r1->need );
     411                                                mergeAssertionSet( need, r2->need );
     412                                                mergeAssertionSet( need, r3->need );
     413                                                ast::AssertionSet have;
     414
     415                                                // unify true and false results, then infer parameters to produce new
     416                                                // candidates
     417                                                ast::ptr< ast::Type > common;
     418                                                if (
     419                                                        unify(
     420                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     421                                                                common )
     422                                                ) {
     423                                                        #warning unimplemented
     424                                                        assert(false);
     425                                                }
     426                                        }
     427                                }
     428                        }
     429                }
     430
     431                void postvisit( const ast::CommaExpr * commaExpr ) {
     432                        ast::TypeEnvironment env{ tenv };
     433                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
     434                       
     435                        CandidateFinder finder2{ symtab, env };
     436                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     437
     438                        for ( const CandidateRef & r2 : finder2.candidates ) {
     439                                addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );
     440                        }
     441                }
     442
     443                void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {
     444                        addCandidate( ctorExpr, tenv );
     445                }
     446
     447                void postvisit( const ast::ConstructorExpr * ctorExpr ) {
     448                        CandidateFinder finder{ symtab, tenv };
     449                        finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
     450                        for ( CandidateRef & r : finder.candidates ) {
     451                                addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );
     452                        }
     453                }
     454
     455                void postvisit( const ast::RangeExpr * rangeExpr ) {
     456                        // resolve low and high, accept candidates where low and high types unify
     457                        CandidateFinder finder1{ symtab, tenv };
     458                        finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
     459                        if ( finder1.candidates.empty() ) return;
     460
     461                        CandidateFinder finder2{ symtab, tenv };
     462                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
     463                        if ( finder2.candidates.empty() ) return;
     464
     465                        for ( const CandidateRef & r1 : finder1.candidates ) {
     466                                for ( const CandidateRef & r2 : finder2.candidates ) {
     467                                        ast::TypeEnvironment env{ r1->env };
     468                                        env.simpleCombine( r2->env );
     469                                        ast::OpenVarSet open{ r1->open };
     470                                        mergeOpenVars( open, r2->open );
     471                                        ast::AssertionSet need;
     472                                        mergeAssertionSet( need, r1->need );
     473                                        mergeAssertionSet( need, r2->need );
     474                                        ast::AssertionSet have;
     475
     476                                        ast::ptr< ast::Type > common;
     477                                        if (
     478                                                unify(
     479                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     480                                                        common )
     481                                        ) {
     482                                                ast::RangeExpr * newExpr =
     483                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
     484                                                newExpr->result = common ? common : r1->expr->result;
     485                                               
     486                                                #warning unimplemented
     487                                                assert(false);
     488                                        }
     489                                }
     490                        }
     491                }
     492
     493                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
     494                        std::vector< CandidateFinder > subCandidates =
     495                                selfFinder.findSubExprs( tupleExpr->exprs );
     496                        std::vector< CandidateList > possibilities;
     497                        combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );
     498
     499                        for ( const CandidateList & subs : possibilities ) {
     500                                std::vector< ast::ptr< ast::Expr > > exprs;
     501                                exprs.reserve( subs.size() );
     502                                for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }
     503
     504                                ast::TypeEnvironment env;
     505                                ast::OpenVarSet open;
     506                                ast::AssertionSet need;
     507                                for ( const CandidateRef & sub : subs ) {
     508                                        env.simpleCombine( sub->env );
     509                                        mergeOpenVars( open, sub->open );
     510                                        mergeAssertionSet( need, sub->need );
     511                                }
     512
     513                                addCandidate(
     514                                        new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },
     515                                        std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );
     516                        }
     517                }
     518
     519                void postvisit( const ast::TupleExpr * tupleExpr ) {
     520                        addCandidate( tupleExpr, tenv );
     521                }
     522
     523                void postvisit( const ast::TupleIndexExpr * tupleExpr ) {
     524                        addCandidate( tupleExpr, tenv );
     525                }
     526
     527                void postvisit( const ast::TupleAssignExpr * tupleExpr ) {
     528                        addCandidate( tupleExpr, tenv );
     529                }
     530
     531                void postvisit( const ast::UniqueExpr * unqExpr ) {
     532                        CandidateFinder finder{ symtab, tenv };
     533                        finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
     534                        for ( CandidateRef & r : finder.candidates ) {
     535                                // ensure that the the id is passed on so that the expressions are "linked"
     536                                addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );
     537                        }
     538                }
     539
     540                void postvisit( const ast::StmtExpr * stmtExpr ) {
     541                        #warning unimplemented
     542                        (void)stmtExpr;
     543                        assert(false);
     544                }
     545
     546                void postvisit( const ast::UntypedInitExpr * initExpr ) {
     547                        #warning unimplemented
     548                        (void)initExpr;
     549                        assert(false);
     550                }
     551
     552                void postvisit( const ast::InitExpr * ) {
     553                        assertf( false, "CandidateFinder should never see a resolved InitExpr." );
     554                }
     555
     556                void postvisit( const ast::DeletedExpr * ) {
     557                        assertf( false, "CandidateFinder should never see a DeletedExpr." );
     558                }
     559
     560                void postvisit( const ast::GenericExpr * ) {
     561                        assertf( false, "_Generic is not yet supported." );
     562                }
     563        };
     564
     565        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     566        /// return type. Skips ambiguous candidates.
     567        CandidateList pruneCandidates( CandidateList & candidates ) {
     568                struct PruneStruct {
     569                        CandidateRef candidate;
     570                        bool ambiguous;
     571
     572                        PruneStruct() = default;
     573                        PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
     574                };
     575
     576                // find lowest-cost candidate for each type
     577                std::unordered_map< std::string, PruneStruct > selected;
     578                for ( CandidateRef & candidate : candidates ) {
     579                        std::string mangleName;
     580                        {
     581                                ast::ptr< ast::Type > newType = candidate->expr->result;
     582                                candidate->env.apply( newType );
     583                                mangleName = Mangle::mangle( newType );
     584                        }
     585
     586                        auto found = selected.find( mangleName );
     587                        if ( found != selected.end() ) {
     588                                if ( candidate->cost < found->second.candidate->cost ) {
     589                                        PRINT(
     590                                                std::cerr << "cost " << candidate->cost << " beats "
     591                                                        << found->second.candidate->cost << std::endl;
     592                                        )
     593
     594                                        found->second = PruneStruct{ candidate };
     595                                } else if ( candidate->cost == found->second.candidate->cost ) {
     596                                        // if one of the candidates contains a deleted identifier, can pick the other,
     597                                        // since deleted expressions should not be ambiguous if there is another option
     598                                        // that is at least as good
     599                                        if ( findDeletedExpr( candidate->expr ) ) {
     600                                                // do nothing
     601                                                PRINT( std::cerr << "candidate is deleted" << std::endl; )
     602                                        } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
     603                                                PRINT( std::cerr << "current is deleted" << std::endl; )
     604                                                found->second = PruneStruct{ candidate };
     605                                        } else {
     606                                                PRINT( std::cerr << "marking ambiguous" << std::endl; )
     607                                                found->second.ambiguous = true;
     608                                        }
     609                                } else {
     610                                        PRINT(
     611                                                std::cerr << "cost " << candidate->cost << " loses to "
     612                                                        << found->second.candidate->cost << std::endl;
     613                                        )
     614                                }
     615                        } else {
     616                                selected.emplace_hint( found, mangleName, candidate );
     617                        }
     618                }
     619
     620                // report unambiguous min-cost candidates
     621                CandidateList out;
     622                for ( auto & target : selected ) {
     623                        if ( target.second.ambiguous ) continue;
     624
     625                        CandidateRef cand = target.second.candidate;
     626                       
     627                        ast::ptr< ast::Type > newResult = cand->expr->result;
     628                        cand->env.applyFree( newResult );
     629                        cand->expr = ast::mutate_field(
     630                                cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
     631                       
     632                        out.emplace_back( cand );
     633                }
     634                return out;
     635        }
     636
     637} // anonymous namespace
     638
    22639void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {
    23         #warning unimplemented
    24         (void)expr; (void)mode;
    25         assert(false);
     640        // Find alternatives for expression
     641        ast::Pass<Finder> finder{ *this };
     642        expr->accept( finder );
     643
     644        if ( mode.failFast && candidates.empty() ) {
     645                SemanticError( expr, "No reasonable alternatives for expression " );
     646        }
     647
     648        if ( mode.satisfyAssns || mode.prune ) {
     649                // trim candidates to just those where the assertions are satisfiable
     650                // - necessary pre-requisite to pruning
     651                CandidateList satisfied;
     652                std::vector< std::string > errors;
     653                for ( auto & candidate : candidates ) {
     654                        satisfyAssertions( *candidate, symtab, satisfied, errors );
     655                }
     656
     657                // fail early if none such
     658                if ( mode.failFast && satisfied.empty() ) {
     659                        std::ostringstream stream;
     660                        stream << "No alternatives with satisfiable assertions for " << expr << "\n";
     661                        for ( const auto& err : errors ) {
     662                                stream << err;
     663                        }
     664                        SemanticError( expr->location, stream.str() );
     665                }
     666
     667                // reset candidates
     668                candidates = std::move( satisfied );
     669        }
     670
     671        if ( mode.prune ) {
     672                // trim candidates to single best one
     673                PRINT(
     674                        std::cerr << "alternatives before prune:" << std::endl;
     675                        print( std::cerr, candidates );
     676                )
     677
     678                CandidateList pruned = pruneCandidates( candidates );
     679               
     680                if ( mode.failFast && pruned.empty() ) {
     681                        std::ostringstream stream;
     682                        CandidateList winners = findMinCost( candidates );
     683                        stream << "Cannot choose between " << winners.size() << " alternatives for "
     684                                "expression\n";
     685                        ast::print( stream, expr );
     686                        stream << " Alternatives are:\n";
     687                        print( stream, winners, 1 );
     688                        SemanticError( expr->location, stream.str() );
     689                }
     690
     691                auto oldsize = candidates.size();
     692                candidates = std::move( pruned );
     693
     694                PRINT(
     695                        std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
     696                )
     697                PRINT(
     698                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     699                                << std::endl;
     700                )
     701        }
     702
     703        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
     704        // adjusted
     705        if ( mode.adjust ) {
     706                for ( CandidateRef & r : candidates ) {
     707                        r->expr = ast::mutate_field(
     708                                r->expr.get(), &ast::Expr::result,
     709                                adjustExprType( r->expr->result, r->env, symtab ) );
     710                }
     711        }
     712
     713        // Central location to handle gcc extension keyword, etc. for all expressions
     714        for ( CandidateRef & r : candidates ) {
     715                if ( r->expr->extension != expr->extension ) {
     716                        r->expr.get_and_mutate()->extension = expr->extension;
     717                }
     718        }
     719}
     720
     721std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     722        const std::vector< ast::ptr< ast::Expr > > & xs
     723) {
     724        std::vector< CandidateFinder > out;
     725
     726        for ( const auto & x : xs ) {
     727                out.emplace_back( symtab, env );
     728                out.back().find( x, ResolvMode::withAdjustment() );
     729               
     730                PRINT(
     731                        std::cerr << "findSubExprs" << std::endl;
     732                        print( std::cerr, out.back().candidates );
     733                )
     734        }
     735
     736        return out;
    26737}
    27738
  • src/ResolvExpr/CandidateFinder.hpp

    raaeacf4 r21300d7  
    1919#include "ResolvMode.h"
    2020#include "AST/Fwd.hpp"
     21#include "AST/Node.hpp"
    2122#include "AST/SymbolTable.hpp"
    2223#include "AST/TypeEnvironment.hpp"
     
    2930        const ast::SymbolTable & symtab;         ///< Symbol table to lookup candidates
    3031        const ast::TypeEnvironment & env;        ///< Substitutions performed in this resolution
    31         const ast::Type * targetType = nullptr;  ///< Target type for resolution
     32        ast::ptr< ast::Type > targetType = nullptr;  ///< Target type for resolution
    3233
    3334        CandidateFinder( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
     
    3637        /// Fill candidates with feasible resolutions for `expr`
    3738        void find( const ast::Expr * expr, ResolvMode mode = {} );
     39
     40        /// Runs new candidate finder on each element in xs, returning the list of finders
     41        std::vector< CandidateFinder > findSubExprs( const std::vector< ast::ptr< ast::Expr > > & xs );
     42
     43        using value_type = CandidateList::value_type;
     44        using iterator = CandidateList::iterator;
     45        using const_iterator = CandidateList::const_iterator;
     46
     47        iterator begin() { return candidates.begin(); }
     48        const_iterator begin() const { return candidates.begin(); }
     49       
     50        iterator end() { return candidates.end(); }
     51        const_iterator end() const { return candidates.end(); }
    3852};
    3953
  • src/ResolvExpr/CurrentObject.cc

    raaeacf4 r21300d7  
    946946        }
    947947
    948         void CurrentObject::setNext( const ast::Designation * designation ) {
     948        const Designation * CurrentObject::findNext( const Designation * designation ) {
     949                using DesignatorChain = std::deque< ptr< Expr > >;
     950                PRINT( std::cerr << "___findNext" << std::endl; )
     951               
     952                // find all the d's
     953                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     954                std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
     955                for ( const Expr * expr : designation->designators ) {
     956                        PRINT( std::cerr << "____untyped: " << expr << std::endl; )
     957                        auto dit = desigAlts.begin();
     958                        if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) {
     959                                for ( const Type * t : curTypes ) {
     960                                        assert( dit != desigAlts.end() );
     961
     962                                        DesignatorChain & d = *dit;
     963                                        PRINT( std::cerr << "____actual: " << t << std::endl; )
     964                                        if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
     965                                                // concatenate identical field names
     966                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
     967                                                        if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
     968                                                                PRINT( std::cerr << "____alt: " << field->type << std::endl; )
     969                                                                DesignatorChain d2 = d;
     970                                                                d2.emplace_back( new VariableExpr{ expr->location, field } );
     971                                                                newDesigAlts.emplace_back( std::move( d2 ) );
     972                                                                newTypes.emplace_back( field->type );
     973                                                        }
     974                                                }
     975                                        }
     976
     977                                        ++dit;
     978                                }
     979                        } else {
     980                                for ( const Type * t : curTypes ) {
     981                                        assert( dit != desigAlts.end() );
     982
     983                                        DesignatorChain & d = *dit;
     984                                        if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
     985                                                PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
     986                                                d.emplace_back( expr );
     987                                                newDesigAlts.emplace_back( d );
     988                                                newTypes.emplace_back( at->base );
     989                                        }
     990                                }
     991                        }
     992
     993                        // reset queue
     994                        desigAlts = std::move( newDesigAlts );
     995                        newDesigAlts.clear();
     996                        curTypes = std::move( newTypes );
     997                        newTypes.clear();
     998                        assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
     999                }
     1000
     1001                if ( desigAlts.size() > 1 ) {
     1002                        SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
     1003                } else if ( desigAlts.empty() ) {
     1004                        SemanticError( designation, "No reasonable alternatives for designation: " );
     1005                }
     1006
     1007                DesignatorChain & d = desigAlts.back();
     1008                PRINT( for ( Expression * expr : d ) {
     1009                        std::cerr << "____desig: " << expr << std::endl;
     1010                } ) // for
     1011                assertf( ! curTypes.empty(), "empty designator chosen");
     1012
     1013                // set new designators
     1014                assertf( ! objStack.empty(), "empty object stack when setting designation" );
     1015                Designation * actualDesignation =
     1016                        new Designation{ designation->location, DesignatorChain{d} };
     1017                objStack.back()->setPosition( d ); // destroys d
     1018                return actualDesignation;
     1019        }
     1020
     1021        void CurrentObject::setNext( const Designation * designation ) {
    9491022                PRINT( std::cerr << "____setNext" << designation << std::endl; )
    9501023                assertf( ! objStack.empty(), "obj stack empty in setNext" );
  • src/ResolvExpr/CurrentObject.h

    raaeacf4 r21300d7  
    111111                CurrentObject( const CodeLocation & loc, const Type * type );
    112112
     113                /// resolves unresolved designation
     114                const Designation * findNext( const Designation * designation );
    113115                /// sets current position using the resolved designation
    114116                void setNext( const ast::Designation * designation );
  • src/ResolvExpr/ExplodedActual.cc

    raaeacf4 r21300d7  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Alternative.h --
     7// ExplodedActual.cc --
    88//
    99// Author           : Aaron B. Moss
     
    2424        }
    2525}
     26
     27// Local Variables: //
     28// tab-width: 4 //
     29// mode: c++ //
     30// compile-command: "make install" //
     31// End: //
  • src/ResolvExpr/ExplodedActual.h

    raaeacf4 r21300d7  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Alternative.h --
     7// ExplodedActual.h --
    88//
    99// Author           : Aaron B. Moss
     
    3737        };
    3838}
     39
     40// Local Variables: //
     41// tab-width: 4 //
     42// mode: c++ //
     43// compile-command: "make install" //
     44// End: //
  • src/ResolvExpr/ResolvMode.h

    raaeacf4 r21300d7  
    2222                const bool prune;            ///< Prune alternatives to min-cost per return type? [true]
    2323                const bool failFast;         ///< Fail on no resulting alternatives? [true]
    24                 const bool resolveAssns;     ///< Resolve assertions? [false]
     24                const bool satisfyAssns;     ///< Satisfy assertions? [false]
    2525
    2626        private:
    27                 constexpr ResolvMode(bool a, bool p, bool ff, bool ra)
    28                 : adjust(a), prune(p), failFast(ff), resolveAssns(ra) {}
     27                constexpr ResolvMode(bool a, bool p, bool ff, bool sa)
     28                : adjust(a), prune(p), failFast(ff), satisfyAssns(sa) {}
    2929
    3030        public:
    3131                /// Default settings
    32                 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), resolveAssns(false) {}
     32                constexpr ResolvMode() : adjust(false), prune(true), failFast(true), satisfyAssns(false) {}
    3333               
    3434                /// With adjust flag set; turns array and function types into equivalent pointers
     
    4343                static constexpr ResolvMode withoutFailFast() { return { true, true, false, false }; }
    4444
    45                 /// The same mode, but with resolveAssns turned on; for top-level calls
     45                /// The same mode, but with satisfyAssns turned on; for top-level calls
    4646                ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; }
    4747        };
  • src/ResolvExpr/Resolver.cc

    raaeacf4 r21300d7  
    3535#include "AST/Print.hpp"
    3636#include "AST/SymbolTable.hpp"
     37#include "AST/Type.hpp"
    3738#include "Common/PassVisitor.h"          // for PassVisitor
    3839#include "Common/SemanticError.h"        // for SemanticError
     
    956957                        }
    957958                };
    958 
    959                 /// Check if this expression is or includes a deleted expression
    960                 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    961                         ast::Pass<DeleteFinder_new> finder;
    962                         expr->accept( finder );
    963                         return finder.pass.delExpr;
    964                 }
    965 
     959        } // anonymous namespace
     960
     961        /// Check if this expression is or includes a deleted expression
     962        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
     963                ast::Pass<DeleteFinder_new> finder;
     964                expr->accept( finder );
     965                return finder.pass.delExpr;
     966        }
     967
     968        namespace {
    966969                /// always-accept candidate filter
    967970                bool anyCandidate( const Candidate & ) { return true; }
     
    10231026
    10241027                        // promote candidate.cvtCost to .cost
    1025                         for ( CandidateRef & cand : winners ) {
    1026                                 cand->cost = cand->cvtCost;
    1027                         }
     1028                        promoteCvtCost( winners );
    10281029
    10291030                        // produce ambiguous errors, if applicable
     
    10991100                        StripCasts_new::strip( expr );
    11001101                }
    1101 
    1102                 /// Find the expression candidate that is the unique best match for `untyped` in a `void`
    1103                 /// context.
    1104                 ast::ptr< ast::Expr > resolveInVoidContext(
    1105                         const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
    1106                 ) {
    1107                         assertf( expr, "expected a non-null expression" );
    1108                        
    1109                         // set up and resolve expression cast to void
    1110                         ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr };
    1111                         CandidateRef choice = findUnfinishedKindExpression(
    1112                                 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
    1113                        
    1114                         // a cast expression has either 0 or 1 interpretations (by language rules);
    1115                         // if 0, an exception has already been thrown, and this code will not run
    1116                         const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
    1117                         env = std::move( choice->env );
    1118 
    1119                         return castExpr->arg;
    1120                 }
    1121 
     1102        } // anonymous namespace
     1103
     1104               
     1105        ast::ptr< ast::Expr > resolveInVoidContext(
     1106                const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
     1107        ) {
     1108                assertf( expr, "expected a non-null expression" );
     1109               
     1110                // set up and resolve expression cast to void
     1111                ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr };
     1112                CandidateRef choice = findUnfinishedKindExpression(
     1113                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     1114               
     1115                // a cast expression has either 0 or 1 interpretations (by language rules);
     1116                // if 0, an exception has already been thrown, and this code will not run
     1117                const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
     1118                env = std::move( choice->env );
     1119
     1120                return castExpr->arg;
     1121        }
     1122
     1123        namespace {
    11221124                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11231125                /// context.
     
    11461148                }
    11471149
     1150                /// Resolve `untyped` to the single expression whose candidate is the best match
     1151                ast::ptr< ast::Expr > findSingleExpression(
     1152                        const ast::Expr * untyped, const ast::SymbolTable & symtab
     1153                ) {
     1154                        return findKindExpression( untyped, symtab );
     1155                }
     1156
    11481157                /// Resolve `untyped` to the single expression whose candidate is the best match for the
    11491158                /// given type.
     
    11521161                ) {
    11531162                        assert( untyped && type );
    1154                         const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1155                         ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
     1163                        ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1164                        ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    11561165                        removeExtraneousCast( newExpr, symtab );
    11571166                        return newExpr;
     
    11891198                        return false;
    11901199                }
     1200
     1201                /// Advance a type itertor to the next mutex parameter
     1202                template<typename Iter>
     1203                inline bool nextMutex( Iter & it, const Iter & end ) {
     1204                        while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
     1205                        return it != end;
     1206                }
    11911207        }
    11921208
     
    12131229                void previsit( const ast::PointerType * );
    12141230
    1215                 const ast::ExprStmt *   previsit( const ast::ExprStmt * );
    1216                 const ast::AsmExpr *    previsit( const ast::AsmExpr * );
    1217                 const ast::AsmStmt *    previsit( const ast::AsmStmt * );
    1218                 const ast::IfStmt *     previsit( const ast::IfStmt * );
    1219                 const ast::WhileStmt *  previsit( const ast::WhileStmt * );
    1220                 const ast::ForStmt *    previsit( const ast::ForStmt * );
    1221                 const ast::SwitchStmt * previsit( const ast::SwitchStmt * );
    1222                 const ast::CaseStmt *   previsit( const ast::CaseStmt * );
    1223                 const ast::BranchStmt * previsit( const ast::BranchStmt * );
    1224                 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );
    1225                 const ast::ThrowStmt *  previsit( const ast::ThrowStmt * );
    1226                 const ast::CatchStmt *  previsit( const ast::CatchStmt * );
    1227                 void previsit( const ast::WaitForStmt * );
    1228 
    1229                 const ast::SingleInit * previsit( const ast::SingleInit * );
    1230                 const ast::ListInit * previsit( const ast::ListInit * );
    1231                 void previsit( const ast::ConstructorInit * );
     1231                const ast::ExprStmt *        previsit( const ast::ExprStmt * );
     1232                const ast::AsmExpr *         previsit( const ast::AsmExpr * );
     1233                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
     1234                const ast::IfStmt *          previsit( const ast::IfStmt * );
     1235                const ast::WhileStmt *       previsit( const ast::WhileStmt * );
     1236                const ast::ForStmt *         previsit( const ast::ForStmt * );
     1237                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
     1238                const ast::CaseStmt *        previsit( const ast::CaseStmt * );
     1239                const ast::BranchStmt *      previsit( const ast::BranchStmt * );
     1240                const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
     1241                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
     1242                const ast::CatchStmt *       previsit( const ast::CatchStmt * );
     1243                const ast::WaitForStmt *    previsit( const ast::WaitForStmt * );
     1244
     1245                const ast::SingleInit *      previsit( const ast::SingleInit * );
     1246                const ast::ListInit *        previsit( const ast::ListInit * );
     1247                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    12321248        };
    12331249
     
    13811397                                "expression." );
    13821398                       
    1383                         const ast::Expr * untyped =
     1399                        ast::ptr< ast::Expr > untyped =
    13841400                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1385                         ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
     1401                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
    13861402                       
    13871403                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    14011417                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    14021418                        // computed goto argument is void*
     1419                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    14031420                        branchStmt = ast::mutate_field(
    14041421                                branchStmt, &ast::BranchStmt::computedTarget,
    1405                                 findSingleExpression(
    1406                                         branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
    1407                                         symtab ) );
     1422                                findSingleExpression( branchStmt->computedTarget, target, symtab ) );
    14081423                }
    14091424                return branchStmt;
     
    14451460        }
    14461461
    1447         void Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
    1448                 #warning unimplemented; Resolver port in progress
    1449                 (void)stmt;
    1450                 assert(false);
     1462        const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
     1463                visit_children = false;
     1464
     1465                // Resolve all clauses first
     1466                for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
     1467                        const ast::WaitForStmt::Clause & clause = stmt->clauses[i];
     1468
     1469                        ast::TypeEnvironment env;
     1470                        CandidateFinder funcFinder{ symtab, env };
     1471
     1472                        // Find all candidates for a function in canonical form
     1473                        funcFinder.find( clause.target.func, ResolvMode::withAdjustment() );
     1474
     1475                        if ( funcFinder.candidates.empty() ) {
     1476                                stringstream ss;
     1477                                ss << "Use of undeclared indentifier '";
     1478                                ss << clause.target.func.strict_as< ast::NameExpr >()->name;
     1479                                ss << "' in call to waitfor";
     1480                                SemanticError( stmt->location, ss.str() );
     1481                        }
     1482
     1483                        if ( clause.target.args.empty() ) {
     1484                                SemanticError( stmt->location,
     1485                                        "Waitfor clause must have at least one mutex parameter");
     1486                        }
     1487
     1488                        // Find all alternatives for all arguments in canonical form
     1489                        std::vector< CandidateFinder > argFinders =
     1490                                funcFinder.findSubExprs( clause.target.args );
     1491                       
     1492                        // List all combinations of arguments
     1493                        std::vector< CandidateList > possibilities;
     1494                        combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
     1495
     1496                        // For every possible function:
     1497                        // * try matching the arguments to the parameters, not the other way around because
     1498                        //   more arguments than parameters
     1499                        CandidateList funcCandidates;
     1500                        std::vector< CandidateList > argsCandidates;
     1501                        SemanticErrorException errors;
     1502                        for ( CandidateRef & func : funcFinder.candidates ) {
     1503                                try {
     1504                                        auto pointerType = dynamic_cast< const ast::PointerType * >(
     1505                                                func->expr->result->stripReferences() );
     1506                                        if ( ! pointerType ) {
     1507                                                SemanticError( stmt->location, func->expr->result.get(),
     1508                                                        "candidate not viable: not a pointer type\n" );
     1509                                        }
     1510
     1511                                        auto funcType = pointerType->base.as< ast::FunctionType >();
     1512                                        if ( ! funcType ) {
     1513                                                SemanticError( stmt->location, func->expr->result.get(),
     1514                                                        "candidate not viable: not a function type\n" );
     1515                                        }
     1516
     1517                                        {
     1518                                                auto param    = funcType->params.begin();
     1519                                                auto paramEnd = funcType->params.end();
     1520
     1521                                                if( ! nextMutex( param, paramEnd ) ) {
     1522                                                        SemanticError( stmt->location, funcType,
     1523                                                                "candidate function not viable: no mutex parameters\n");
     1524                                                }
     1525                                        }
     1526
     1527                                        CandidateRef func2{ new Candidate{ *func } };
     1528                                        // strip reference from function
     1529                                        func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
     1530
     1531                                        // Each argument must be matched with a parameter of the current candidate
     1532                                        for ( auto & argsList : possibilities ) {
     1533                                                try {
     1534                                                        // Declare data structures needed for resolution
     1535                                                        ast::OpenVarSet open;
     1536                                                        ast::AssertionSet need, have;
     1537                                                        ast::TypeEnvironment resultEnv{ func->env };
     1538                                                        // Add all type variables as open so that those not used in the
     1539                                                        // parameter list are still considered open
     1540                                                        resultEnv.add( funcType->forall );
     1541
     1542                                                        // load type variables from arguments into one shared space
     1543                                                        for ( auto & arg : argsList ) {
     1544                                                                resultEnv.simpleCombine( arg->env );
     1545                                                        }
     1546
     1547                                                        // Make sure we don't widen any existing bindings
     1548                                                        resultEnv.forbidWidening();
     1549
     1550                                                        // Find any unbound type variables
     1551                                                        resultEnv.extractOpenVars( open );
     1552
     1553                                                        auto param = funcType->params.begin();
     1554                                                        auto paramEnd = funcType->params.end();
     1555
     1556                                                        unsigned n_mutex_param = 0;
     1557
     1558                                                        // For every argument of its set, check if it matches one of the
     1559                                                        // parameters. The order is important
     1560                                                        for ( auto & arg : argsList ) {
     1561                                                                // Ignore non-mutex arguments
     1562                                                                if ( ! nextMutex( param, paramEnd ) ) {
     1563                                                                        // We ran out of parameters but still have arguments.
     1564                                                                        // This function doesn't match
     1565                                                                        SemanticError( stmt->location, funcType,
     1566                                                                                toString("candidate function not viable: too many mutex "
     1567                                                                                "arguments, expected ", n_mutex_param, "\n" ) );
     1568                                                                }
     1569
     1570                                                                ++n_mutex_param;
     1571
     1572                                                                // Check if the argument matches the parameter type in the current
     1573                                                                // scope
     1574                                                                ast::ptr< ast::Type > paramType = (*param)->get_type();
     1575                                                                if (
     1576                                                                        ! unify(
     1577                                                                                arg->expr->result, paramType, resultEnv, need, have, open,
     1578                                                                                symtab )
     1579                                                                ) {
     1580                                                                        // Type doesn't match
     1581                                                                        stringstream ss;
     1582                                                                        ss << "candidate function not viable: no known conversion "
     1583                                                                                "from '";
     1584                                                                        ast::print( ss, (*param)->get_type() );
     1585                                                                        ss << "' to '";
     1586                                                                        ast::print( ss, arg->expr->result );
     1587                                                                        ss << "' with env '";
     1588                                                                        ast::print( ss, resultEnv );
     1589                                                                        ss << "'\n";
     1590                                                                        SemanticError( stmt->location, funcType, ss.str() );
     1591                                                                }
     1592
     1593                                                                ++param;
     1594                                                        }
     1595
     1596                                                        // All arguments match!
     1597
     1598                                                        // Check if parameters are missing
     1599                                                        if ( nextMutex( param, paramEnd ) ) {
     1600                                                                do {
     1601                                                                        ++n_mutex_param;
     1602                                                                        ++param;
     1603                                                                } while ( nextMutex( param, paramEnd ) );
     1604
     1605                                                                // We ran out of arguments but still have parameters left; this
     1606                                                                // function doesn't match
     1607                                                                SemanticError( stmt->location, funcType,
     1608                                                                        toString( "candidate function not viable: too few mutex "
     1609                                                                        "arguments, expected ", n_mutex_param, "\n" ) );
     1610                                                        }
     1611
     1612                                                        // All parameters match!
     1613
     1614                                                        // Finish the expressions to tie in proper environments
     1615                                                        finishExpr( func2->expr, resultEnv );
     1616                                                        for ( CandidateRef & arg : argsList ) {
     1617                                                                finishExpr( arg->expr, resultEnv );
     1618                                                        }
     1619
     1620                                                        // This is a match, store it and save it for later
     1621                                                        funcCandidates.emplace_back( std::move( func2 ) );
     1622                                                        argsCandidates.emplace_back( std::move( argsList ) );
     1623
     1624                                                } catch ( SemanticErrorException & e ) {
     1625                                                        errors.append( e );
     1626                                                }
     1627                                        }
     1628                                } catch ( SemanticErrorException & e ) {
     1629                                        errors.append( e );
     1630                                }
     1631                        }
     1632
     1633                        // Make sure correct number of arguments
     1634                        if( funcCandidates.empty() ) {
     1635                                SemanticErrorException top( stmt->location,
     1636                                        "No alternatives for function in call to waitfor" );
     1637                                top.append( errors );
     1638                                throw top;
     1639                        }
     1640
     1641                        if( argsCandidates.empty() ) {
     1642                                SemanticErrorException top( stmt->location,
     1643                                        "No alternatives for arguments in call to waitfor" );
     1644                                top.append( errors );
     1645                                throw top;
     1646                        }
     1647
     1648                        if( funcCandidates.size() > 1 ) {
     1649                                SemanticErrorException top( stmt->location,
     1650                                        "Ambiguous function in call to waitfor" );
     1651                                top.append( errors );
     1652                                throw top;
     1653                        }
     1654                        if( argsCandidates.size() > 1 ) {
     1655                                SemanticErrorException top( stmt->location,
     1656                                        "Ambiguous arguments in call to waitfor" );
     1657                                top.append( errors );
     1658                                throw top;
     1659                        }
     1660                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
     1661
     1662                        // build new clause
     1663                        ast::WaitForStmt::Clause clause2;
     1664                       
     1665                        clause2.target.func = funcCandidates.front()->expr;
     1666                       
     1667                        clause2.target.args.reserve( clause.target.args.size() );
     1668                        for ( auto arg : argsCandidates.front() ) {
     1669                                clause2.target.args.emplace_back( std::move( arg->expr ) );
     1670                        }
     1671
     1672                        // Resolve the conditions as if it were an IfStmt, statements normally
     1673                        clause2.cond = findSingleExpression( clause.cond, symtab );
     1674                        clause2.stmt = clause.stmt->accept( *visitor );
     1675
     1676                        // set results into stmt
     1677                        auto n = mutate( stmt );
     1678                        n->clauses[i] = std::move( clause2 );
     1679                        stmt = n;
     1680                }
     1681
     1682                if ( stmt->timeout.stmt ) {
     1683                        // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
     1684                        ast::WaitForStmt::Timeout timeout2;
     1685
     1686                        ast::ptr< ast::Type > target =
     1687                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
     1688                        timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
     1689                        timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
     1690                        timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
     1691
     1692                        // set results into stmt
     1693                        auto n = mutate( stmt );
     1694                        n->timeout = std::move( timeout2 );
     1695                        stmt = n;
     1696                }
     1697
     1698                if ( stmt->orElse.stmt ) {
     1699                        // resolve the condition like IfStmt, stmts normally
     1700                        ast::WaitForStmt::OrElse orElse2;
     1701
     1702                        orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
     1703                        orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
     1704
     1705                        // set results into stmt
     1706                        auto n = mutate( stmt );
     1707                        n->orElse = std::move( orElse2 );
     1708                        stmt = n;
     1709                }
     1710
     1711                return stmt;
    14511712        }
    14521713
     
    14571718                // resolve initialization using the possibilities as determined by the `currentObject`
    14581719                // cursor.
    1459                 ast::Expr * untyped = new ast::UntypedInitExpr{
     1720                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    14601721                        singleInit->location, singleInit->value, currentObject.getOptions() };
    1461                 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
     1722                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
    14621723                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    14631724
     
    15101771                        // iterate designations and initializers in pairs, moving the cursor to the current
    15111772                        // designated object and resolving the initializer against that object
    1512                         #warning unimplemented; Resolver port in progress
    1513                         assert(false);
    1514                 }
     1773                        listInit = ast::mutate_field_index(
     1774                                listInit, &ast::ListInit::designations, i,
     1775                                currentObject.findNext( listInit->designations[i] ) );
     1776                        listInit = ast::mutate_field_index(
     1777                                listInit, &ast::ListInit::initializers, i,
     1778                                listInit->initializers[i]->accept( *visitor ) );
     1779                }
     1780
     1781                // move cursor out of brace-enclosed initializer-list
     1782                currentObject.exitListInit();
    15151783
    15161784                visit_children = false;
     
    15181786        }
    15191787
    1520         void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
    1521                 #warning unimplemented; Resolver port in progress
    1522                 (void)ctorInit;
    1523                 assert(false);
     1788        const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
     1789                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
     1790                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
     1791
     1792                // found a constructor - can get rid of C-style initializer
     1793                // xxx - Rob suggests this field is dead code
     1794                ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
     1795
     1796                // intrinsic single-parameter constructors and destructors do nothing. Since this was
     1797                // implicitly generated, there's no way for it to have side effects, so get rid of it to
     1798                // clean up generated code
     1799                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     1800                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
     1801                }
     1802                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     1803                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
     1804                }
     1805
     1806                return ctorInit;
    15241807        }
    15251808
  • src/ResolvExpr/Resolver.h

    raaeacf4 r21300d7  
    1717
    1818#include <list>          // for list
    19 #include <AST/Node.hpp>  // for ptr
     19
     20#include "AST/Node.hpp"  // for ptr
    2021
    2122class ConstructorInit;
     
    2930namespace ast {
    3031        class Decl;
     32        class DeletedExpr;
     33        class SymbolTable;
     34        class TypeEnvironment;
    3135} // namespace ast
    3236
     
    4852        /// Checks types and binds syntactic constructs to typed representations
    4953        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
     54        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
     55        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
     56        /// Find the expression candidate that is the unique best match for `untyped` in a `void`
     57        /// context.
     58        ast::ptr< ast::Expr > resolveInVoidContext(
     59                const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
    5060} // namespace ResolvExpr
    5161
  • src/ResolvExpr/Unify.cc

    raaeacf4 r21300d7  
    11431143                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11441144                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     1145                        ast::OpenVarSet & open, const ast::SymbolTable & symtab
     1146        ) {
     1147                ast::ptr<ast::Type> common;
     1148                return unify( type1, type2, env, need, have, open, symtab, common );
     1149        }
     1150
     1151        bool unify(
     1152                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     1153                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    11451154                        ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    11461155        ) {
  • src/ResolvExpr/Unify.h

    raaeacf4 r21300d7  
    7272                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    7373                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     74                ast::OpenVarSet & open, const ast::SymbolTable & symtab );
     75
     76        bool unify(
     77                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     78                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    7479                ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
    7580
  • src/ResolvExpr/module.mk

    raaeacf4 r21300d7  
    2626      ResolvExpr/CurrentObject.cc \
    2727      ResolvExpr/ExplodedActual.cc \
     28      ResolvExpr/ExplodedArg.cpp \
    2829      ResolvExpr/FindOpenVars.cc \
    2930      ResolvExpr/Occurs.cc \
     
    3536      ResolvExpr/Resolver.cc \
    3637      ResolvExpr/ResolveTypeof.cc \
     38      ResolvExpr/SatisfyAssertions.cpp \
    3739      ResolvExpr/SpecCost.cc \
    3840      ResolvExpr/TypeEnvironment.cc \
  • src/ResolvExpr/typeops.h

    raaeacf4 r21300d7  
    7171                } // while
    7272        }
     73
     74        /// Replaces array types with equivalent pointer, and function types with a pointer-to-function
     75        const ast::Type * adjustExprType(
     76                const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
    7377
    7478        // in CastCost.cc
Note: See TracChangeset for help on using the changeset viewer.