Changes in / [8568319:3cd5fdd]


Ignore:
Location:
src
Files:
4 added
11 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Print.hpp

    r8568319 r3cd5fdd  
    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

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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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

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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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

    r8568319 r3cd5fdd  
    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   }
    4643};
    4744
Note: See TracChangeset for help on using the changeset viewer.