Changes in / [8568319:3cd5fdd]
- Location:
- src
- Files:
-
- 4 added
- 11 edited
-
AST/Print.hpp (modified) (1 diff)
-
AST/SymbolTable.hpp (modified) (1 diff)
-
AST/porting.md (modified) (1 diff)
-
Common/Indenter.h (modified) (1 diff)
-
Makefile.in (modified) (4 diffs)
-
ResolvExpr/AlternativeFinder.cc (modified) (1 diff)
-
ResolvExpr/Candidate.cpp (added)
-
ResolvExpr/Candidate.hpp (added)
-
ResolvExpr/CandidateFinder.cpp (added)
-
ResolvExpr/CandidateFinder.hpp (added)
-
ResolvExpr/ResolveAssertions.cc (modified) (2 diffs)
-
ResolvExpr/Resolver.cc (modified) (12 diffs)
-
ResolvExpr/module.mk (modified) (1 diff)
-
ResolvExpr/typeops.h (modified) (1 diff)
-
SynTree/BaseSyntaxNode.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Print.hpp
r8568319 r3cd5fdd 29 29 void print( std::ostream & os, const ast::Node * node, Indenter indent = {} ); 30 30 31 /// Wrap any standard format printer (matching above) with integer Indenter constructor32 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 37 31 /// Print a declaration in its short form 38 32 void printShort( std::ostream & os, const ast::Decl * node, Indenter indent = {} ); 39 33 40 34 inline 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 } ); 42 36 } 43 37 -
src/AST/SymbolTable.hpp
r8568319 r3cd5fdd 85 85 86 86 public: 87 explicitSymbolTable();87 SymbolTable(); 88 88 ~SymbolTable(); 89 89 -
src/AST/porting.md
r8568319 r3cd5fdd 295 295 * changed `WidenMode widenMode` => `WidenMode widen` 296 296 297 `Alternative` => `Candidate` 298 * `openVars` => `open` 299 297 300 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes 298 301 -
src/Common/Indenter.h
r8568319 r3cd5fdd 18 18 19 19 struct Indenter { 20 static unsigned tabsize; 20 static unsigned tabsize; ///< default number of spaces in one level of indentation 21 21 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 25 24 25 Indenter( unsigned int indent = 0, unsigned int amt = tabsize ) 26 : indent( indent*amt ), amt( amt ) {} 27 26 28 Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; } 27 29 Indenter & operator-=(int nlevels) { indent -= amt*nlevels; return *this; } -
src/Makefile.in
r8568319 r3cd5fdd 189 189 ResolvExpr/Alternative.$(OBJEXT) \ 190 190 ResolvExpr/AlternativeFinder.$(OBJEXT) \ 191 ResolvExpr/Candidate.$(OBJEXT) \ 192 ResolvExpr/CandidateFinder.$(OBJEXT) \ 191 193 ResolvExpr/CastCost.$(OBJEXT) ResolvExpr/CommonType.$(OBJEXT) \ 192 194 ResolvExpr/ConversionCost.$(OBJEXT) \ … … 622 624 ResolvExpr/Alternative.cc \ 623 625 ResolvExpr/AlternativeFinder.cc \ 626 ResolvExpr/Candidate.cpp \ 627 ResolvExpr/CandidateFinder.cpp \ 624 628 ResolvExpr/CastCost.cc \ 625 629 ResolvExpr/CommonType.cc \ … … 872 876 ResolvExpr/AlternativeFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 873 877 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 878 ResolvExpr/Candidate.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 879 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 880 ResolvExpr/CandidateFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 881 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 874 882 ResolvExpr/CastCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 875 883 ResolvExpr/$(DEPDIR)/$(am__dirstamp) … … 1254 1262 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AlternativeFinder.Po@am__quote@ 1255 1263 @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@ 1256 1266 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CastCost.Po@am__quote@ 1257 1267 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CommonType.Po@am__quote@ -
src/ResolvExpr/AlternativeFinder.cc
r8568319 r3cd5fdd 136 136 137 137 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) { 138 Indenter indent = { Indenter::tabsize,indentAmt };138 Indenter indent = { indentAmt }; 139 139 for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) { 140 140 i->print( os, indent ); -
src/ResolvExpr/ResolveAssertions.cc
r8568319 r3cd5fdd 365 365 // fail early if any assertion is not resolvable 366 366 if ( ! resolveAssertion( assn, resn ) ) { 367 Indenter tabs{ Indenter::tabsize,3 };367 Indenter tabs{ 3 }; 368 368 std::ostringstream ss; 369 369 ss << tabs << "Unsatisfiable alternative:\n"; … … 391 391 // fail early if no mutually-compatible assertion satisfaction 392 392 if ( compatible.empty() ) { 393 Indenter tabs{ Indenter::tabsize,3 };393 Indenter tabs{ 3 }; 394 394 std::ostringstream ss; 395 395 ss << tabs << "Unsatisfiable alternative:\n"; -
src/ResolvExpr/Resolver.cc
r8568319 r3cd5fdd 21 21 #include "Alternative.h" // for Alternative, AltList 22 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp" 24 #include "CandidateFinder.hpp" 23 25 #include "CurrentObject.h" // for CurrentObject 24 26 #include "RenameVars.h" // for RenameVars, global_renamer … … 31 33 #include "AST/Init.hpp" 32 34 #include "AST/Pass.hpp" 35 #include "AST/Print.hpp" 33 36 #include "AST/SymbolTable.hpp" 34 37 #include "Common/PassVisitor.h" // for PassVisitor … … 116 119 117 120 namespace { 118 struct DeleteFinder : public WithShortCircuiting {121 struct DeleteFinder_old : public WithShortCircuiting { 119 122 DeletedExpr * delExpr = nullptr; 120 123 void previsit( DeletedExpr * expr ) { … … 130 133 131 134 DeletedExpr * findDeletedExpr( Expression * expr ) { 132 PassVisitor<DeleteFinder > finder;135 PassVisitor<DeleteFinder_old> finder; 133 136 expr->accept( finder ); 134 137 return finder.pass.delExpr; … … 136 139 137 140 namespace { 138 struct StripCasts {141 struct StripCasts_old { 139 142 Expression * postmutate( CastExpr * castExpr ) { 140 143 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 149 152 150 153 static void strip( Expression *& expr ) { 151 PassVisitor<StripCasts > stripper;154 PassVisitor<StripCasts_old> stripper; 152 155 expr = expr->acceptMutator( stripper ); 153 156 } … … 157 160 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 158 161 env.makeSubstitution( *expr->env ); 159 StripCasts ::strip( expr ); // remove unnecessary casts that may be buried in an expression162 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 160 163 } 161 164 … … 940 943 /////////////////////////////////////////////////////////////////////////// 941 944 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 942 1121 class Resolver_new final 943 1122 : public ast::WithSymbolTable, public ast::WithGuards, … … 947 1126 ast::ptr< ast::Type > functionReturn = nullptr; 948 1127 // ast::CurrentObject currentObject = nullptr; 949 //bool inEnumDecl = false;1128 bool inEnumDecl = false; 950 1129 951 1130 public: … … 953 1132 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 954 1133 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 * ); 981 1160 }; 982 1161 … … 1004 1183 ast::chain_mutate( ret ) 1005 1184 ( &ast::FunctionDecl::type ) 1006 ( &ast::FunctionType::params ) 1007 [i] 1185 ( &ast::FunctionType::params )[i] 1008 1186 ( &ast::ObjectDecl::init ) 1009 1187 ( &ast::SingleInit::value )->env = nullptr; … … 1023 1201 } 1024 1202 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; 1035 1218 } 1036 1219 -
src/ResolvExpr/module.mk
r8568319 r3cd5fdd 19 19 ResolvExpr/Alternative.cc \ 20 20 ResolvExpr/AlternativeFinder.cc \ 21 ResolvExpr/Candidate.cpp \ 22 ResolvExpr/CandidateFinder.cpp \ 21 23 ResolvExpr/CastCost.cc \ 22 24 ResolvExpr/CommonType.cc \ -
src/ResolvExpr/typeops.h
r8568319 r3cd5fdd 103 103 104 104 bool typesCompatible( 105 const ast::Type *, const ast::Type *, const ast::SymbolTable & ,105 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {}, 106 106 const ast::TypeEnvironment & env = {} ); 107 107 -
src/SynTree/BaseSyntaxNode.h
r8568319 r3cd5fdd 41 41 /// * Expressions should not finish with a newline, since the expression's parent has better information. 42 42 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 }46 43 }; 47 44
Note:
See TracChangeset
for help on using the changeset viewer.