Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    rf02f546 r251ce80  
    3232#include "AST/Type.hpp"
    3333#include "AST/TypeEnvironment.hpp"
    34 #include "Common/Eval.h"            // for eval
    3534#include "Common/PassVisitor.h"     // for PassVisitor
    3635#include "CommonType.hpp"           // for commonType
     
    161160                env.apply( newSecond );
    162161
    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 );
    165164
    166165                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
     
    780779        }
    781780
    782         // Unification of Expressions
    783         //
    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 always
    789         // sees distinct ast::VariableExpr objects at these positions
    790 
    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 types
    842                                 if ( ! unifyExact(
    843                                         e1->result, e2c->result, tenv, need, have, open, widen ) ) return;
    844 
    845                                 // inspect casts' inner expressions
    846                                 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 object
    866                                 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 
    903781        class Unify_new final : public ast::WithShortCircuiting {
    904782                const ast::Type * type2;
     
    942820                        if ( ! array2 ) return;
    943821
     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
    944824                        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;
    952834                        }
    953835
     
    1082964                        // check that the other type is compatible and named the same
    1083965                        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;
    1086967                        return otherInst;
    1087968                }
     
    11681049
    11691050                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 );
    11751053                }
    11761054
     
    12831161        ) {
    12841162                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 );
    12871165                return unifyInexact(
    12881166                        type1, type2, env, need, have, open, WidenMode{ true, true }, common );
     
    13011179                        entry1 = var1 ? open.find( *var1 ) : open.end(),
    13021180                        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
    13091184                if ( isopen1 && isopen2 ) {
    13101185                        if ( entry1->second.kind != entry2->second.kind ) return false;
     
    13151190                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen );
    13161191                } 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 {
    13291194                        return ast::Pass<Unify_new>::read(
    13301195                                type1, type2, env, need, have, open, widen );
    13311196                }
    1332                
    13331197        }
    13341198
Note: See TracChangeset for help on using the changeset viewer.