Ignore:
Timestamp:
Jun 18, 2019, 11:47:44 AM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
a2a85658, b408364
Parents:
bc92bee
Message:

Start porting CastExpr? resolution

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    rbc92bee rc8e4d2f8  
    2828#include "ExplodedArg.hpp"
    2929#include "Resolver.h"
     30#include "ResolveTypeof.h"
    3031#include "SatisfyAssertions.hpp"
    3132#include "typeops.h"              // for adjustExprType, conversionCost, polyCost, specCost
     
    3839#include "AST/Type.hpp"
    3940#include "SymTab/Mangler.h"
     41#include "SymTab/Validate.h"      // for validateType
    4042#include "Tuples/Tuples.h"        // for handleTupleAssignment
    4143
     
    554556        }
    555557
     558        /// Generate a cast expression from `arg` to `toType`
     559        const ast::Expr * restructureCast( const ast::Expr * arg, const ast::Type * toType, bool isGenerated ) {
     560                #warning unimplemented
     561                (void)arg; (void)toType; (void)isGenerated;
     562                assert(false);
     563                return nullptr;
     564        }
     565
    556566        /// Actually visits expressions to find their candidate interpretations
    557567        struct Finder final : public ast::WithShortCircuiting {
     
    741751                /// Adds implicit struct-conversions to the alternative list
    742752                void addAnonConversions( const CandidateRef & cand ) {
    743                         #warning unimplemented
    744                         (void)cand;
    745                         assert(false);
     753                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     754                        // it's okay for the aggregate expression to have reference type -- cast it to the
     755                        // base type to treat the aggregate as the referenced value
     756                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
     757                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
     758                        cand->env.apply( aggrType );
     759                       
     760                        if ( aggrType.as< ast::ReferenceType >() ) {
     761                                aggrExpr =
     762                                        new ast::CastExpr{ aggrExpr->location, aggrExpr, aggrType->stripReferences() };
     763                        }
     764
     765                        if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {
     766                                addAggMembers( structInst, aggrExpr, cand, Cost::safe, "" );
     767                        } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
     768                                addAggMembers( unionInst, aggrExpr, cand, Cost::safe, "" );
     769                        }
     770                }
     771
     772                /// Adds aggregate member interpretations
     773                void addAggMembers(
     774                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     775                        const CandidateRef & cand, const Cost & addedCost, const std::string & name
     776                ) {
     777                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
     778                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
     779                                CandidateRef newCand = std::make_shared<Candidate>(
     780                                        *cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
     781                                // add anonymous member interpretations whenever an aggregate value type is seen
     782                                // as a member expression
     783                                addAnonConversions( newCand );
     784                                candidates.emplace_back( move( newCand ) );
     785                        }
    746786                }
    747787
     
    915955
    916956                void postvisit( const ast::CastExpr * castExpr ) {
     957                        ast::ptr< ast::Type > toType = castExpr->result;
     958                        assert( toType );
     959                        toType = resolveTypeof( toType, symtab );
     960                        toType = SymTab::validateType( toType, symtab );
     961                        toType = adjustExprType( toType, tenv, symtab );
     962
     963                        CandidateFinder finder{ symtab, tenv, toType };
     964                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
     965
     966                        CandidateList matches;
     967                        for ( CandidateRef & cand : finder.candidates ) {
     968                                ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     969                                ast::OpenVarSet open( cand->open );
     970
     971                                cand->env.extractOpenVars( open );
     972
     973                                // It is possible that a cast can throw away some values in a multiply-valued
     974                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     975                                // subexpression results that are cast directly. The candidate is invalid if it
     976                                // has fewer results than there are types to cast to.
     977                                int discardedValues = cand->expr->result->size() - toType->size();
     978                                if ( discardedValues < 0 ) continue;
     979
     980                                // unification run for side-effects
     981                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
     982                                Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     983                                PRINT(
     984                                        std::cerr << "working on cast with result: " << toType << std::endl;
     985                                        std::cerr << "and expr type: " << cand->expr->result << std::endl;
     986                                        std::cerr << "env: " << cand->env << std::endl;
     987                                )
     988                                if ( thisCost != Cost::infinity ) {
     989                                        PRINT(
     990                                                std::cerr << "has finite cost." << std::endl;
     991                                        )
     992                                        // count one safe conversion for each value that is thrown away
     993                                        thisCost.incSafe( discardedValues );
     994                                        CandidateRef newCand = std::make_shared<Candidate>(
     995                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     996                                                copy( cand->env ), move( open ), move( need ), cand->cost,
     997                                                cand->cost + thisCost );
     998                                        inferParameters( newCand, matches );
     999                                }
     1000                        }
     1001
     1002                        // castExpr->result should be replaced with toType
     1003                        // candidates => matches
     1004
    9171005                        #warning unimplemented
    9181006                        (void)castExpr;
     
    9271015                        for ( CandidateRef & r : finder.candidates ) {
    9281016                                addCandidate(
    929                                         *r, new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
     1017                                        *r,
     1018                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    9301019                        }
    9311020                }
Note: See TracChangeset for help on using the changeset viewer.