Changeset 99d4584 for src/ResolvExpr
- Timestamp:
- Jun 5, 2019, 5:58:38 PM (5 years ago)
- 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
- Location:
- src/ResolvExpr
- Files:
-
- 4 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r2a8f0c1 r99d4584 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
r2a8f0c1 r99d4584 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
r2a8f0c1 r99d4584 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 … … 30 32 #include "AST/Init.hpp" 31 33 #include "AST/Pass.hpp" 34 #include "AST/Print.hpp" 32 35 #include "AST/SymbolTable.hpp" 33 36 #include "Common/PassVisitor.h" // for PassVisitor … … 115 118 116 119 namespace { 117 struct DeleteFinder : public WithShortCircuiting {120 struct DeleteFinder_old : public WithShortCircuiting { 118 121 DeletedExpr * delExpr = nullptr; 119 122 void previsit( DeletedExpr * expr ) { … … 129 132 130 133 DeletedExpr * findDeletedExpr( Expression * expr ) { 131 PassVisitor<DeleteFinder > finder;134 PassVisitor<DeleteFinder_old> finder; 132 135 expr->accept( finder ); 133 136 return finder.pass.delExpr; … … 135 138 136 139 namespace { 137 struct StripCasts {140 struct StripCasts_old { 138 141 Expression * postmutate( CastExpr * castExpr ) { 139 142 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 148 151 149 152 static void strip( Expression *& expr ) { 150 PassVisitor<StripCasts > stripper;153 PassVisitor<StripCasts_old> stripper; 151 154 expr = expr->acceptMutator( stripper ); 152 155 } … … 156 159 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 157 160 env.makeSubstitution( *expr->env ); 158 StripCasts ::strip( expr ); // remove unnecessary casts that may be buried in an expression161 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 159 162 } 160 163 … … 939 942 /////////////////////////////////////////////////////////////////////////// 940 943 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 941 1120 class Resolver_new final 942 1121 : public ast::WithSymbolTable, public ast::WithGuards, … … 946 1125 ast::ptr< ast::Type > functionReturn = nullptr; 947 1126 // ast::CurrentObject currentObject = nullptr; 948 //bool inEnumDecl = false;1127 bool inEnumDecl = false; 949 1128 950 1129 public: … … 952 1131 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 953 1132 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 * ); 980 1159 }; 981 1160 … … 1018 1197 } 1019 1198 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; 1030 1214 } 1031 1215 -
src/ResolvExpr/module.mk
r2a8f0c1 r99d4584 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
r2a8f0c1 r99d4584 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
Note: See TracChangeset
for help on using the changeset viewer.