Changeset 432ce7a


Ignore:
Timestamp:
Jun 11, 2019, 5:52:50 PM (2 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
arm-eh, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
6625727
Parents:
4b7cce6
Message:

Port CandidateFinder::postvisit for UntypedExpr?, stub dependencies

Location:
src
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Print.hpp

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    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/AlternativeFinder.cc

    r4b7cce6 r432ce7a  
    116116                /// Finds matching alternatives for a function, given a set of arguments
    117117                template<typename OutputIterator>
    118                 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 );
    119119                /// Sets up parameter inference for an output alternative
    120120                template< typename OutputIterator >
     
    593593
    594594                /// Gets the list of exploded alternatives for this pack
    595                 const ExplodedActual& getExpl( const ExplodedArgs& args ) const {
     595                const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
    596596                        return args[nextArg-1][explAlt];
    597597                }
     
    617617        /// Instantiates an argument to match a formal, returns false if no results left
    618618        bool instantiateArgument( Type* formalType, Initializer* initializer,
    619                         const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
     619                        const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
    620620                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    621621                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    889889        template<typename OutputIterator>
    890890        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    891                         FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
     891                        FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
    892892                OpenVarSet funcOpenVars;
    893893                AssertionSet funcNeed, funcHave;
     
    10211021
    10221022                // pre-explode arguments
    1023                 ExplodedArgs argExpansions;
     1023                ExplodedArgs_old argExpansions;
    10241024                argExpansions.reserve( argAlternatives.size() );
    10251025
  • src/ResolvExpr/AlternativeFinder.h

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    7070using CandidateList = std::vector< CandidateRef >;
    7171
     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
    7285/// Sum the cost of a list of candidates
    7386static inline Cost sumCost( const CandidateList & candidates ) {
  • src/ResolvExpr/CandidateFinder.cpp

    r4b7cce6 r432ce7a  
    1616#include "CandidateFinder.hpp"
    1717
     18#include <deque>
    1819#include <iterator>               // for back_inserter
    1920#include <sstream>
    2021#include <string>
    2122#include <unordered_map>
     23#include <vector>
    2224
    2325#include "Candidate.hpp"
    2426#include "CompilationState.h"
    2527#include "Cost.h"
     28#include "ExplodedArg.hpp"
    2629#include "Resolver.h"
    2730#include "SatisfyAssertions.hpp"
     
    3336#include "AST/Print.hpp"
    3437#include "AST/SymbolTable.hpp"
     38#include "AST/Type.hpp"
    3539#include "SymTab/Mangler.h"
     40#include "Tuples/Tuples.h"        // for handleTupleAssignment
    3641
    3742#define PRINT( text ) if ( resolvep ) { text }
     
    4045
    4146namespace {
     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        }
    4276
    4377        /// Actually visits expressions to find their candidate interpretations
     
    6599                }
    66100
     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
    67118                void postvisit( const ast::UntypedExpr * untypedExpr ) {
    68                         #warning unimplemented
    69                         (void)untypedExpr;
    70                         assert(false);
     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                        }
    71266                }
    72267
     
    440635        }
    441636
    442         /// Returns a list of alternatives with the minimum cost in the given list
    443         CandidateList findMinCost( const CandidateList & candidates ) {
    444                 CandidateList out;
    445                 Cost minCost = Cost::infinity;
    446                 for ( const CandidateRef & r : candidates ) {
    447                         if ( r->cost < minCost ) {
    448                                 minCost = r->cost;
    449                                 out.clear();
    450                                 out.emplace_back( r );
    451                         } else if ( r->cost == minCost ) {
    452                                 out.emplace_back( r );
    453                         }
    454                 }
    455                 return out;
    456         }
    457 
    458637} // anonymous namespace
    459638
  • src/ResolvExpr/ExplodedActual.cc

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    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/module.mk

    r4b7cce6 r432ce7a  
    2626      ResolvExpr/CurrentObject.cc \
    2727      ResolvExpr/ExplodedActual.cc \
     28      ResolvExpr/ExplodedArg.cpp \
    2829      ResolvExpr/FindOpenVars.cc \
    2930      ResolvExpr/Occurs.cc \
  • src/Tuples/Explode.h

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    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

    r4b7cce6 r432ce7a  
    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.