Changes in / [04396aa:6625727]


Ignore:
Location:
src
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Print.hpp

    r04396aa r6625727  
    1616#pragma once
    1717
    18 #include <iosfwd>
    19 #include <utility> // for forward
     18#include <iostream>
     19#include <utility>   // for forward
    2020
    2121#include "AST/Node.hpp"
     
    3232void printShort( std::ostream & os, const ast::Decl * node, Indenter indent = {} );
    3333
    34 inline void printShort( std::ostream & os, const ast::Decl * node, unsigned int indent ) {
    35     printShort( os, node, Indenter{ indent } );
     34/// Print a collection of items
     35template< typename Coll >
     36void printAll( std::ostream & os, const Coll & c, Indenter indent = {} ) {
     37    for ( const auto & i : c ) {
     38        if ( ! i ) continue;
     39       
     40        os << indent;
     41        print( os, i, indent );
     42        os << std::endl;
     43    }
    3644}
    3745
  • src/AST/porting.md

    r04396aa r6625727  
    299299* `openVars` => `open`
    300300
     301`ExplodedActual` => `ExplodedArg`
     302* `ExplodedActual.h` => `ExplodedArg.hpp`
     303
    301304[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
    302305
  • src/Makefile.in

    r04396aa r6625727  
    195195        ResolvExpr/CurrentObject.$(OBJEXT) \
    196196        ResolvExpr/ExplodedActual.$(OBJEXT) \
     197        ResolvExpr/ExplodedArg.$(OBJEXT) \
    197198        ResolvExpr/FindOpenVars.$(OBJEXT) ResolvExpr/Occurs.$(OBJEXT) \
    198199        ResolvExpr/PolyCost.$(OBJEXT) \
     
    633634      ResolvExpr/CurrentObject.cc \
    634635      ResolvExpr/ExplodedActual.cc \
     636      ResolvExpr/ExplodedArg.cpp \
    635637      ResolvExpr/FindOpenVars.cc \
    636638      ResolvExpr/Occurs.cc \
     
    895897ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    896898        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     899ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     900        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    897901ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    898902        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     
    12771281@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CurrentObject.Po@am__quote@
    12781282@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedActual.Po@am__quote@
     1283@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedArg.Po@am__quote@
    12791284@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/FindOpenVars.Po@am__quote@
    12801285@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Occurs.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

    r04396aa r6625727  
    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

    r04396aa r6625727  
    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 >
     
    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

    r04396aa r6625727  
    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

    r04396aa r6625727  
    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

    r04396aa r6625727  
    1616#include "CandidateFinder.hpp"
    1717
     18#include <deque>
     19#include <iterator>               // for back_inserter
    1820#include <sstream>
     21#include <string>
     22#include <unordered_map>
     23#include <vector>
    1924
    2025#include "Candidate.hpp"
    2126#include "CompilationState.h"
     27#include "Cost.h"
     28#include "ExplodedArg.hpp"
     29#include "Resolver.h"
    2230#include "SatisfyAssertions.hpp"
     31#include "typeops.h"              // for adjustExprType
     32#include "Unify.h"
    2333#include "AST/Expr.hpp"
    2434#include "AST/Node.hpp"
    2535#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
    2641
    2742#define PRINT( text ) if ( resolvep ) { text }
     
    3146namespace {
    3247
     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
    3377        /// Actually visits expressions to find their candidate interpretations
    34         struct Finder {
    35                 CandidateFinder & candFinder;
     78        struct Finder final : public ast::WithShortCircuiting {
     79                CandidateFinder & selfFinder;
    3680                const ast::SymbolTable & symtab;
    3781                CandidateList & candidates;
     
    4084
    4185                Finder( CandidateFinder & f )
    42                 : candFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     86                : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
    4387                  targetType( f.targetType ) {}
    4488               
    45                 #warning unimplemented
     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                }
    46563        };
    47564
     
    49566        /// return type. Skips ambiguous candidates.
    50567        CandidateList pruneCandidates( CandidateList & candidates ) {
    51                 #warning unimplemented
    52                 (void)candidates;
    53                 assert(false);
    54                 return {};
     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;
    55635        }
    56636
     
    91671        if ( mode.prune ) {
    92672                // trim candidates to single best one
    93                 auto oldsize = candidates.size();
    94673                PRINT(
    95674                        std::cerr << "alternatives before prune:" << std::endl;
     
    98677
    99678                CandidateList pruned = pruneCandidates( candidates );
     679               
    100680                if ( mode.failFast && pruned.empty() ) {
    101681                        std::ostringstream stream;
    102                         CandidateList winners;
    103                        
    104                         #warning unimplemented
    105                         assert(false);
    106                 }
    107         }
    108 
    109         #warning unimplemented
    110         assert(false);
     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        }
    111719}
    112720
  • src/ResolvExpr/ExplodedActual.cc

    r04396aa r6625727  
    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

    r04396aa r6625727  
    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/Resolver.cc

    r04396aa r6625727  
    957957                        }
    958958                };
    959 
    960                 /// Check if this expression is or includes a deleted expression
    961                 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    962                         ast::Pass<DeleteFinder_new> finder;
    963                         expr->accept( finder );
    964                         return finder.pass.delExpr;
    965                 }
    966 
     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 {
    967969                /// always-accept candidate filter
    968970                bool anyCandidate( const Candidate & ) { return true; }
     
    10241026
    10251027                        // promote candidate.cvtCost to .cost
    1026                         for ( CandidateRef & cand : winners ) {
    1027                                 cand->cost = cand->cvtCost;
    1028                         }
     1028                        promoteCvtCost( winners );
    10291029
    10301030                        // produce ambiguous errors, if applicable
     
    11001100                        StripCasts_new::strip( expr );
    11011101                }
    1102 
    1103                 /// Find the expression candidate that is the unique best match for `untyped` in a `void`
    1104                 /// context.
    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 
     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 {
    11231124                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11241125                /// context.
  • src/ResolvExpr/Resolver.h

    r04396aa r6625727  
    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/module.mk

    r04396aa r6625727  
    2626      ResolvExpr/CurrentObject.cc \
    2727      ResolvExpr/ExplodedActual.cc \
     28      ResolvExpr/ExplodedArg.cpp \
    2829      ResolvExpr/FindOpenVars.cc \
    2930      ResolvExpr/Occurs.cc \
  • src/ResolvExpr/typeops.h

    r04396aa r6625727  
    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
  • src/Tuples/Explode.h

    r04396aa r6625727  
    1919#include <utility>                      // for forward
    2020
     21#include "AST/Expr.hpp"
    2122#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
     23#include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    2224#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
     25#include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    2326#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    2427#include "SynTree/Type.h"               // for TupleType, Type
    2528#include "Tuples.h"                     // for maybeImpure
     29
     30namespace ast {
     31        class SymbolTable;
     32}
    2633
    2734namespace SymTab {
     
    130137                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    131138        }
     139
     140/// helper function used by explode
     141template< typename Output >
     142void explodeUnique(
     143        const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab,
     144        Output && out, bool isTupleAssign
     145) {
     146        #warning unimplemented
     147        (void)expr; (void)arg; (void)symtab; (void)out; (void)isTupleAssign;
     148        assert(false);
     149}
     150
     151/// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
     152template< typename Output >
     153void explode(
     154        const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
     155        bool isTupleAssign = false
     156) {
     157        explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );
     158}
     159
    132160} // namespace Tuples
    133161
  • src/Tuples/TupleAssignment.cc

    r04396aa r6625727  
    377377                }
    378378        }
     379
     380        void handleTupleAssignment(
     381                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
     382                std::vector< ResolvExpr::CandidateFinder > & args
     383        ) {
     384                #warning unimplmented
     385                (void)finder; (void)assign; (void)args;
     386                assert(false);
     387        }
    379388} // namespace Tuples
    380389
  • src/Tuples/Tuples.h

    r04396aa r6625727  
    2626
    2727#include "ResolvExpr/AlternativeFinder.h"
     28#include "ResolvExpr/CandidateFinder.hpp"
    2829
    2930namespace Tuples {
     
    3132        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    3233                std::vector< ResolvExpr::AlternativeFinder >& args );
     34        void handleTupleAssignment(
     35                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
     36                std::vector< ResolvExpr::CandidateFinder > & args );
    3337
    3438        // TupleExpansion.cc
Note: See TracChangeset for help on using the changeset viewer.