Changeset 99d4584 for src/ResolvExpr


Ignore:
Timestamp:
Jun 5, 2019, 5:58:38 PM (5 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:
3cd5fdd
Parents:
2a8f0c1
Message:

Further stubs for resolver port

  • also switched order of constructor params on Indenter
Location:
src/ResolvExpr
Files:
4 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r2a8f0c1 r99d4584  
    136136
    137137        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
    138                 Indenter indent = { Indenter::tabsize, indentAmt };
     138                Indenter indent = { indentAmt };
    139139                for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    140140                        i->print( os, indent );
  • src/ResolvExpr/ResolveAssertions.cc

    r2a8f0c1 r99d4584  
    365365                                        // fail early if any assertion is not resolvable
    366366                                        if ( ! resolveAssertion( assn, resn ) ) {
    367                                                 Indenter tabs{ Indenter::tabsize, 3 };
     367                                                Indenter tabs{ 3 };
    368368                                                std::ostringstream ss;
    369369                                                ss << tabs << "Unsatisfiable alternative:\n";
     
    391391                                        // fail early if no mutually-compatible assertion satisfaction
    392392                                        if ( compatible.empty() ) {
    393                                                 Indenter tabs{ Indenter::tabsize, 3 };
     393                                                Indenter tabs{ 3 };
    394394                                                std::ostringstream ss;
    395395                                                ss << tabs << "Unsatisfiable alternative:\n";
  • src/ResolvExpr/Resolver.cc

    r2a8f0c1 r99d4584  
    2121#include "Alternative.h"                 // for Alternative, AltList
    2222#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
     23#include "Candidate.hpp"
     24#include "CandidateFinder.hpp"
    2325#include "CurrentObject.h"               // for CurrentObject
    2426#include "RenameVars.h"                  // for RenameVars, global_renamer
     
    3032#include "AST/Init.hpp"
    3133#include "AST/Pass.hpp"
     34#include "AST/Print.hpp"
    3235#include "AST/SymbolTable.hpp"
    3336#include "Common/PassVisitor.h"          // for PassVisitor
     
    115118
    116119        namespace {
    117                 struct DeleteFinder : public WithShortCircuiting        {
     120                struct DeleteFinder_old : public WithShortCircuiting    {
    118121                        DeletedExpr * delExpr = nullptr;
    119122                        void previsit( DeletedExpr * expr ) {
     
    129132
    130133        DeletedExpr * findDeletedExpr( Expression * expr ) {
    131                 PassVisitor<DeleteFinder> finder;
     134                PassVisitor<DeleteFinder_old> finder;
    132135                expr->accept( finder );
    133136                return finder.pass.delExpr;
     
    135138
    136139        namespace {
    137                 struct StripCasts {
     140                struct StripCasts_old {
    138141                        Expression * postmutate( CastExpr * castExpr ) {
    139142                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     
    148151
    149152                        static void strip( Expression *& expr ) {
    150                                 PassVisitor<StripCasts> stripper;
     153                                PassVisitor<StripCasts_old> stripper;
    151154                                expr = expr->acceptMutator( stripper );
    152155                        }
     
    156159                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    157160                        env.makeSubstitution( *expr->env );
    158                         StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
     161                        StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
    159162                }
    160163
     
    939942        ///////////////////////////////////////////////////////////////////////////
    940943
     944        namespace {
     945                /// Finds deleted expressions in an expression tree
     946                struct DeleteFinder_new final : public ast::WithShortCircuiting {
     947                        const ast::DeletedExpr * delExpr = nullptr;
     948
     949                        void previsit( const ast::DeletedExpr * expr ) {
     950                                if ( delExpr ) { visit_children = false; }
     951                                else { delExpr = expr; }
     952                        }
     953
     954                        void previsit( const ast::Expr * ) {
     955                                if ( delExpr ) { visit_children = false; }
     956                        }
     957                };
     958
     959                /// Check if this expression is or includes a deleted expression
     960                const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
     961                        ast::Pass<DeleteFinder_new> finder;
     962                        expr->accept( finder );
     963                        return finder.pass.delExpr;
     964                }
     965
     966                /// Calls the CandidateFinder and finds the single best candidate
     967                CandidateRef findUnfinishedKindExpression(
     968                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
     969                        std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
     970                ) {
     971                        if ( ! untyped ) return nullptr;
     972
     973                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     974                        static unsigned recursion_level = 0;
     975
     976                        ++recursion_level;
     977                        ast::TypeEnvironment env;
     978                        CandidateFinder finder{ symtab, env };
     979                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     980                        --recursion_level;
     981
     982                        // produce a filtered list of candidates
     983                        CandidateList candidates;
     984                        for ( auto & cand : finder.candidates ) {
     985                                if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
     986                        }
     987
     988                        // produce invalid error if no candidates
     989                        if ( candidates.empty() ) {
     990                                SemanticError( untyped,
     991                                        toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
     992                                        "expression: ") );
     993                        }
     994
     995                        // search for cheapest candidate
     996                        CandidateList winners;
     997                        bool seen_undeleted = false;
     998                        for ( CandidateRef & cand : candidates ) {
     999                                int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
     1000
     1001                                if ( c > 0 ) continue;  // skip more expensive than winner
     1002
     1003                                if ( c < 0 ) {
     1004                                        // reset on new cheapest
     1005                                        seen_undeleted = ! findDeletedExpr( cand->expr );
     1006                                        winners.clear();
     1007                                } else /* if ( c == 0 ) */ {
     1008                                        if ( findDeletedExpr( cand->expr ) ) {
     1009                                                // skip deleted expression if already seen one equivalent-cost not
     1010                                                if ( seen_undeleted ) continue;
     1011                                        } else if ( ! seen_undeleted ) {
     1012                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     1013                                                winners.clear();
     1014                                                seen_undeleted = true;
     1015                                        }
     1016                                }
     1017
     1018                                winners.emplace_back( std::move( cand ) );
     1019                        }
     1020
     1021                        // promote candidate.cvtCost to .cost
     1022                        for ( CandidateRef & cand : winners ) {
     1023                                cand->cost = cand->cvtCost;
     1024                        }
     1025
     1026                        // produce ambiguous errors, if applicable
     1027                        if ( winners.size() != 1 ) {
     1028                                std::ostringstream stream;
     1029                                stream << "Cannot choose between " << winners.size() << " alternatives for "
     1030                                        << kind << (kind != "" ? " " : "") << "expression\n";
     1031                                ast::print( stream, untyped );
     1032                                stream << " Alternatives are:\n";
     1033                                print( stream, winners, 1 );
     1034                                SemanticError( untyped->location, stream.str() );
     1035                        }
     1036
     1037                        // single selected choice
     1038                        CandidateRef & choice = winners.front();
     1039
     1040                        // fail on only expression deleted
     1041                        if ( ! seen_undeleted ) {
     1042                                SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
     1043                                "includes deleted identifier in " );
     1044                        }
     1045
     1046                        return std::move( choice );
     1047                }
     1048
     1049                /// Strips extraneous casts out of an expression
     1050                struct StripCasts_new final {
     1051                        const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
     1052                                if (
     1053                                        castExpr->isGenerated
     1054                                        && typesCompatible( castExpr->arg->result, castExpr->result )
     1055                                ) {
     1056                                        // generated cast is the same type as its argument, remove it after keeping env
     1057                                        ast::ptr<ast::Expr> arg = castExpr->arg;
     1058                                        arg.get_and_mutate()->env = castExpr->env;
     1059                                        return arg;
     1060                                }
     1061                                return castExpr;
     1062                        }
     1063
     1064                        static void strip( ast::ptr< ast::Expr > & expr ) {
     1065                                ast::Pass< StripCasts_new > stripper;
     1066                                expr = expr->accept( stripper );
     1067                        }
     1068                };
     1069
     1070                /// Establish post-resolver invariants for expressions
     1071                void finishExpr(
     1072                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
     1073                        const ast::TypeSubstitution * oldenv = nullptr
     1074                ) {
     1075                        // set up new type substitution for expression
     1076                        ast::ptr< ast::TypeSubstitution > newenv =
     1077                                 oldenv ? oldenv : new ast::TypeSubstitution{};
     1078                        env.writeToSubstitution( *newenv.get_and_mutate() );
     1079                        expr.get_and_mutate()->env = std::move( newenv );
     1080                        // remove unncecessary casts
     1081                        StripCasts_new::strip( expr );
     1082                }
     1083               
     1084                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     1085                /// lowest cost, returning the resolved version
     1086                ast::ptr< ast::Expr > findKindExpression(
     1087                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
     1088                        std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
     1089                ) {
     1090                        if ( ! untyped ) return {};
     1091                        CandidateRef choice =
     1092                                findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
     1093                        finishExpr( choice->expr, choice->env, untyped->env );
     1094                        return std::move( choice->expr );
     1095                }
     1096
     1097                /// Predicate for "Candidate has integral type"
     1098                bool hasIntegralType( const Candidate & i ) {
     1099                        const ast::Type * type = i.expr->result;
     1100                       
     1101                        if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
     1102                                return bt->isInteger();
     1103                        } else if (
     1104                                dynamic_cast< const ast::EnumInstType * >( type )
     1105                                || dynamic_cast< const ast::ZeroType * >( type )
     1106                                || dynamic_cast< const ast::OneType * >( type )
     1107                        ) {
     1108                                return true;
     1109                        } else return false;
     1110                }
     1111
     1112                /// Resolve `untyped` as an integral expression, returning the resolved version
     1113                ast::ptr< ast::Expr > findIntegralExpression(
     1114                        const ast::Expr * untyped, const ast::SymbolTable & symtab
     1115                ) {
     1116                        return findKindExpression( untyped, symtab, "condition", hasIntegralType );
     1117                }
     1118        }
     1119
    9411120        class Resolver_new final
    9421121        : public ast::WithSymbolTable, public ast::WithGuards,
     
    9461125                ast::ptr< ast::Type > functionReturn = nullptr;
    9471126                // ast::CurrentObject currentObject = nullptr;
    948                 // bool inEnumDecl = false;
     1127                bool inEnumDecl = false;
    9491128
    9501129        public:
     
    9521131                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    9531132
    954                 void previsit( const ast::FunctionDecl * functionDecl );
    955                 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * functionDecl );
    956                 void previsit( const ast::ObjectDecl * objectDecl );
    957                 void previsit( const ast::EnumDecl * enumDecl );
    958                 void previsit( const ast::StaticAssertDecl * assertDecl );
    959 
    960                 void previsit( const ast::ArrayType * at );
    961                 void previsit( const ast::PointerType * pt );
    962 
    963                 void previsit( const ast::ExprStmt * exprStmt );
    964                 void previsit( const ast::AsmExpr * asmExpr );
    965                 void previsit( const ast::AsmStmt * asmStmt );
    966                 void previsit( const ast::IfStmt * ifStmt );
    967                 void previsit( const ast::WhileStmt * whileStmt );
    968                 void previsit( const ast::ForStmt * forStmt );
    969                 void previsit( const ast::SwitchStmt * switchStmt );
    970                 void previsit( const ast::CaseStmt * caseStmt );
    971                 void previsit( const ast::BranchStmt * branchStmt );
    972                 void previsit( const ast::ReturnStmt * returnStmt );
    973                 void previsit( const ast::ThrowStmt * throwStmt );
    974                 void previsit( const ast::CatchStmt * catchStmt );
    975                 void previsit( const ast::WaitForStmt * stmt );
    976 
    977                 void previsit( const ast::SingleInit * singleInit );
    978                 void previsit( const ast::ListInit * listInit );
    979                 void previsit( const ast::ConstructorInit * ctorInit );
     1133                void previsit( const ast::FunctionDecl * );
     1134                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
     1135                void previsit( const ast::ObjectDecl * );
     1136                void previsit( const ast::EnumDecl * );
     1137                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
     1138
     1139                void previsit( const ast::ArrayType * );
     1140                void previsit( const ast::PointerType * );
     1141
     1142                void previsit( const ast::ExprStmt * );
     1143                void previsit( const ast::AsmExpr * );
     1144                void previsit( const ast::AsmStmt * );
     1145                void previsit( const ast::IfStmt * );
     1146                void previsit( const ast::WhileStmt * );
     1147                void previsit( const ast::ForStmt * );
     1148                void previsit( const ast::SwitchStmt * );
     1149                void previsit( const ast::CaseStmt * );
     1150                void previsit( const ast::BranchStmt * );
     1151                void previsit( const ast::ReturnStmt * );
     1152                void previsit( const ast::ThrowStmt * );
     1153                void previsit( const ast::CatchStmt * );
     1154                void previsit( const ast::WaitForStmt * );
     1155
     1156                void previsit( const ast::SingleInit * );
     1157                void previsit( const ast::ListInit * );
     1158                void previsit( const ast::ConstructorInit * );
    9801159        };
    9811160
     
    10181197        }
    10191198
    1020         void Resolver_new::previsit( const ast::EnumDecl * enumDecl ) {
    1021                 #warning unimplemented; Resolver port in progress
    1022                 (void)enumDecl;
    1023                 assert(false);
    1024         }
    1025 
    1026         void Resolver_new::previsit( const ast::StaticAssertDecl * assertDecl ) {
    1027                 #warning unimplemented; Resolver port in progress
    1028                 (void)assertDecl;
    1029                 assert(false);
     1199        void Resolver_new::previsit( const ast::EnumDecl * ) {
     1200                // in case we decide to allow nested enums
     1201                GuardValue( inEnumDecl );
     1202                inEnumDecl = false;
     1203        }
     1204
     1205        const ast::StaticAssertDecl * Resolver_new::previsit(
     1206                const ast::StaticAssertDecl * assertDecl
     1207        ) {
     1208                ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
     1209                if ( cond == assertDecl->cond ) return assertDecl;
     1210               
     1211                ast::StaticAssertDecl * ret = mutate( assertDecl );
     1212                ret->cond = cond;
     1213                return ret;
    10301214        }
    10311215
  • src/ResolvExpr/module.mk

    r2a8f0c1 r99d4584  
    1919      ResolvExpr/Alternative.cc \
    2020      ResolvExpr/AlternativeFinder.cc \
     21      ResolvExpr/Candidate.cpp \
     22      ResolvExpr/CandidateFinder.cpp \
    2123      ResolvExpr/CastCost.cc \
    2224      ResolvExpr/CommonType.cc \
  • src/ResolvExpr/typeops.h

    r2a8f0c1 r99d4584  
    103103
    104104        bool typesCompatible(
    105                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     105                const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
    106106                const ast::TypeEnvironment & env = {} );
    107107       
Note: See TracChangeset for help on using the changeset viewer.