Changes in src/ResolvExpr/Unify.cc [f02f546:251ce80]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
rf02f546 r251ce80 32 32 #include "AST/Type.hpp" 33 33 #include "AST/TypeEnvironment.hpp" 34 #include "Common/Eval.h" // for eval35 34 #include "Common/PassVisitor.h" // for PassVisitor 36 35 #include "CommonType.hpp" // for commonType … … 161 160 env.apply( newSecond ); 162 161 163 //findOpenVars( newFirst, open, closed, need, have, FirstClosed );164 findOpenVars( newSecond, open, closed, need, have, newEnv,FirstOpen );162 findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 163 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 165 164 166 165 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() ); … … 780 779 } 781 780 782 // Unification of Expressions783 //784 // Boolean outcome (obvious): Are they basically spelled the same?785 // Side effect of binding variables (subtle): if `sizeof(int)` ===_expr `sizeof(T)` then `int` ===_ty `T`786 //787 // Context: if `float[VAREXPR1]` ===_ty `float[VAREXPR2]` then `VAREXPR1` ===_expr `VAREXPR2`788 // where the VAREXPR are meant as notational metavariables representing the fact that unification always789 // sees distinct ast::VariableExpr objects at these positions790 791 static bool unify( const ast::Expr * e1, const ast::Expr * e2, ast::TypeEnvironment & env,792 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,793 WidenMode widen );794 795 class UnifyExpr final : public ast::WithShortCircuiting {796 const ast::Expr * e2;797 ast::TypeEnvironment & tenv;798 ast::AssertionSet & need;799 ast::AssertionSet & have;800 const ast::OpenVarSet & open;801 WidenMode widen;802 public:803 bool result;804 805 private:806 807 void tryMatchOnStaticValue( const ast::Expr * e1 ) {808 Evaluation r1 = eval(e1);809 Evaluation r2 = eval(e2);810 811 if ( ! r1.hasKnownValue ) return;812 if ( ! r2.hasKnownValue ) return;813 814 if (r1.knownValue != r2.knownValue) return;815 816 visit_children = false;817 result = true;818 }819 820 public:821 822 void previsit( const ast::Node * ) { assert(false); }823 824 void previsit( const ast::Expr * e1 ) {825 tryMatchOnStaticValue( e1 );826 visit_children = false;827 }828 829 void previsit( const ast::CastExpr * e1 ) {830 tryMatchOnStaticValue( e1 );831 832 if (result) {833 assert (visit_children == false);834 } else {835 assert (visit_children == true);836 visit_children = false;837 838 auto e2c = dynamic_cast< const ast::CastExpr * >( e2 );839 if ( ! e2c ) return;840 841 // inspect casts' target types842 if ( ! unifyExact(843 e1->result, e2c->result, tenv, need, have, open, widen ) ) return;844 845 // inspect casts' inner expressions846 result = unify( e1->arg, e2c->arg, tenv, need, have, open, widen );847 }848 }849 850 void previsit( const ast::VariableExpr * e1 ) {851 tryMatchOnStaticValue( e1 );852 853 if (result) {854 assert (visit_children == false);855 } else {856 assert (visit_children == true);857 visit_children = false;858 859 auto e2v = dynamic_cast< const ast::VariableExpr * >( e2 );860 if ( ! e2v ) return;861 862 assert(e1->var);863 assert(e2v->var);864 865 // conservative: variable exprs match if their declarations are represented by the same C++ AST object866 result = (e1->var == e2v->var);867 }868 }869 870 void previsit( const ast::SizeofExpr * e1 ) {871 tryMatchOnStaticValue( e1 );872 873 if (result) {874 assert (visit_children == false);875 } else {876 assert (visit_children == true);877 visit_children = false;878 879 auto e2so = dynamic_cast< const ast::SizeofExpr * >( e2 );880 if ( ! e2so ) return;881 882 assert((e1->type != nullptr) ^ (e1->expr != nullptr));883 assert((e2so->type != nullptr) ^ (e2so->expr != nullptr));884 if ( ! (e1->type && e2so->type) ) return;885 886 // expression unification calls type unification (mutual recursion)887 result = unifyExact( e1->type, e2so->type, tenv, need, have, open, widen );888 }889 }890 891 UnifyExpr( const ast::Expr * e2, ast::TypeEnvironment & env, ast::AssertionSet & need,892 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen )893 : e2( e2 ), tenv(env), need(need), have(have), open(open), widen(widen), result(false) {}894 };895 896 static bool unify( const ast::Expr * e1, const ast::Expr * e2, ast::TypeEnvironment & env,897 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,898 WidenMode widen ) {899 assert( e1 && e2 );900 return ast::Pass<UnifyExpr>::read( e1, e2, env, need, have, open, widen );901 }902 903 781 class Unify_new final : public ast::WithShortCircuiting { 904 782 const ast::Type * type2; … … 942 820 if ( ! array2 ) return; 943 821 822 // to unify, array types must both be VLA or both not VLA and both must have a 823 // dimension expression or not have a dimension 944 824 if ( array->isVarLen != array2->isVarLen ) return; 945 if ( (array->dimension != nullptr) != (array2->dimension != nullptr) ) return; 946 947 if ( array->dimension ) { 948 assert( array2->dimension ); 949 // type unification calls expression unification (mutual recursion) 950 if ( ! unify(array->dimension, array2->dimension, 951 tenv, need, have, open, widen) ) return; 825 if ( ! array->isVarLen && ! array2->isVarLen 826 && array->dimension && array2->dimension ) { 827 auto ce1 = array->dimension.as< ast::ConstantExpr >(); 828 auto ce2 = array2->dimension.as< ast::ConstantExpr >(); 829 830 // see C11 Reference Manual 6.7.6.2.6 831 // two array types with size specifiers that are integer constant expressions are 832 // compatible if both size specifiers have the same constant value 833 if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return; 952 834 } 953 835 … … 1082 964 // check that the other type is compatible and named the same 1083 965 auto otherInst = dynamic_cast< const XInstType * >( other ); 1084 if (otherInst && inst->name == otherInst->name) 1085 this->result = otherInst; 966 if (otherInst && inst->name == otherInst->name) this->result = otherInst; 1086 967 return otherInst; 1087 968 } … … 1168 1049 1169 1050 void postvisit( const ast::TypeInstType * typeInst ) { 1170 // assert( open.find( *typeInst ) == open.end() ); 1171 auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 ); 1172 if (otherInst && typeInst->name == otherInst->name) 1173 this->result = otherInst; 1174 // return otherInst; 1051 assert( open.find( *typeInst ) == open.end() ); 1052 handleRefType( typeInst, type2 ); 1175 1053 } 1176 1054 … … 1283 1161 ) { 1284 1162 ast::OpenVarSet closed; 1285 //findOpenVars( type1, open, closed, need, have, FirstClosed );1286 findOpenVars( type2, open, closed, need, have, env,FirstOpen );1163 findOpenVars( type1, open, closed, need, have, FirstClosed ); 1164 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1287 1165 return unifyInexact( 1288 1166 type1, type2, env, need, have, open, WidenMode{ true, true }, common ); … … 1301 1179 entry1 = var1 ? open.find( *var1 ) : open.end(), 1302 1180 entry2 = var2 ? open.find( *var2 ) : open.end(); 1303 // bool isopen1 = entry1 != open.end(); 1304 // bool isopen2 = entry2 != open.end(); 1305 bool isopen1 = var1 && env.lookup(*var1); 1306 bool isopen2 = var2 && env.lookup(*var2); 1307 1308 /* 1181 bool isopen1 = entry1 != open.end(); 1182 bool isopen2 = entry2 != open.end(); 1183 1309 1184 if ( isopen1 && isopen2 ) { 1310 1185 if ( entry1->second.kind != entry2->second.kind ) return false; … … 1315 1190 return env.bindVar( var1, type2, entry1->second, need, have, open, widen ); 1316 1191 } else if ( isopen2 ) { 1317 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); 1318 } */ 1319 if ( isopen1 && isopen2 ) { 1320 if ( var1->base->kind != var2->base->kind ) return false; 1321 return env.bindVarToVar( 1322 var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have, 1323 open, widen ); 1324 } else if ( isopen1 ) { 1325 return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen ); 1326 } else if ( isopen2 ) { 1327 return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen ); 1328 }else { 1192 return env.bindVar( var2, type1, entry2->second, need, have, open, widen ); 1193 } else { 1329 1194 return ast::Pass<Unify_new>::read( 1330 1195 type1, type2, env, need, have, open, widen ); 1331 1196 } 1332 1333 1197 } 1334 1198
Note:
See TracChangeset
for help on using the changeset viewer.