Changeset 99d4584


Ignore:
Timestamp:
Jun 5, 2019, 5:58:38 PM (3 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
arm-eh, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
3cd5fdd
Parents:
2a8f0c1
Message:

Further stubs for resolver port

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

Legend:

Unmodified
Added
Removed
  • src/AST/Print.hpp

    r2a8f0c1 r99d4584  
    2929void print( std::ostream & os, const ast::Node * node, Indenter indent = {} );
    3030
    31 /// Wrap any standard format printer (matching above) with integer Indenter constructor
    32 template<typename T>
    33 inline void print( std::ostream & os, T && x, unsigned int indent ) {
    34     print( os, std::forward<T>(x), Indenter{ Indenter::tabsize, indent });
    35 }
    36 
    3731/// Print a declaration in its short form
    3832void printShort( std::ostream & os, const ast::Decl * node, Indenter indent = {} );
    3933
    4034inline void printShort( std::ostream & os, const ast::Decl * node, unsigned int indent ) {
    41     printShort( os, node, Indenter{ Indenter::tabsize, indent } );
     35    printShort( os, node, Indenter{ indent } );
    4236}
    4337
  • src/AST/SymbolTable.hpp

    r2a8f0c1 r99d4584  
    8585
    8686public:
    87         explicit SymbolTable();
     87        SymbolTable();
    8888        ~SymbolTable();
    8989
  • src/AST/porting.md

    r2a8f0c1 r99d4584  
    295295* changed `WidenMode widenMode` => `WidenMode widen`
    296296
     297`Alternative` => `Candidate`
     298* `openVars` => `open`
     299
    297300[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
    298301
  • src/Common/Indenter.h

    r2a8f0c1 r99d4584  
    1818
    1919struct Indenter {
    20         static unsigned tabsize;
     20        static unsigned tabsize;  ///< default number of spaces in one level of indentation
    2121
    22         Indenter( unsigned int amt = tabsize, unsigned int indent = 0 ) : amt( amt ), indent( indent ) {}
    23         unsigned int amt;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
    24         unsigned int indent;
     22        unsigned int indent;      ///< number of spaces to indent
     23        unsigned int amt;         ///< spaces in one level of indentation
    2524
     25        Indenter( unsigned int indent = 0, unsigned int amt = tabsize )
     26        : indent( indent*amt ), amt( amt ) {}
     27       
    2628        Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; }
    2729        Indenter & operator-=(int nlevels) { indent -= amt*nlevels; return *this; }
  • src/Makefile.in

    r2a8f0c1 r99d4584  
    189189        ResolvExpr/Alternative.$(OBJEXT) \
    190190        ResolvExpr/AlternativeFinder.$(OBJEXT) \
     191        ResolvExpr/Candidate.$(OBJEXT) \
     192        ResolvExpr/CandidateFinder.$(OBJEXT) \
    191193        ResolvExpr/CastCost.$(OBJEXT) ResolvExpr/CommonType.$(OBJEXT) \
    192194        ResolvExpr/ConversionCost.$(OBJEXT) \
     
    622624      ResolvExpr/Alternative.cc \
    623625      ResolvExpr/AlternativeFinder.cc \
     626      ResolvExpr/Candidate.cpp \
     627      ResolvExpr/CandidateFinder.cpp \
    624628      ResolvExpr/CastCost.cc \
    625629      ResolvExpr/CommonType.cc \
     
    872876ResolvExpr/AlternativeFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    873877        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     878ResolvExpr/Candidate.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     879        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     880ResolvExpr/CandidateFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     881        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    874882ResolvExpr/CastCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    875883        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     
    12541262@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AlternativeFinder.Po@am__quote@
    12551263@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AlternativePrinter.Po@am__quote@
     1264@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Candidate.Po@am__quote@
     1265@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CandidateFinder.Po@am__quote@
    12561266@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CastCost.Po@am__quote@
    12571267@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CommonType.Po@am__quote@
  • 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       
  • src/SynTree/BaseSyntaxNode.h

    r2a8f0c1 r99d4584  
    4141  /// * Expressions should not finish with a newline, since the expression's parent has better information.
    4242        virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
    43   void print( std::ostream & os, unsigned int indent ) {
    44     print( os, Indenter{ Indenter::tabsize, indent });
    45   }
     43  // void print( std::ostream & os, unsigned int indent ) {
     44  //   print( os, Indenter{ indent });
     45  // }
    4646};
    4747
Note: See TracChangeset for help on using the changeset viewer.