Ignore:
Timestamp:
Aug 14, 2024, 1:12:18 PM (2 months ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
master
Children:
2f31773
Parents:
1a2ba84
Message:

Fix #175

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/GenPoly.cpp

    r1a2ba84 rf9ad69d  
    2727#include "AST/Type.hpp"
    2828#include "AST/TypeSubstitution.hpp"
     29#include "Common/Eval.hpp"                // for eval
    2930#include "GenPoly/ErasableScopedMap.hpp"  // for ErasableScopedMap<>::const_...
    3031#include "ResolvExpr/Typeops.hpp"         // for flatten
     
    243244} // namespace
    244245
     246// This function, and its helpers following, have logic duplicated from
     247// unification.  The difference in context is that unification applies where
     248// the types "must" match, while this variation applies to arbitrary type
     249// pairs, when an optimization could apply if they happen to match.  This
     250// variation does not bind type variables.  The helper functions support
     251// the case for matching ArrayType.
     252bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );
     253
     254static bool exprsPolyCompatibleByStaticValue(
     255                const ast::Expr * e1, const ast::Expr * e2 ) {
     256        Evaluation r1 = eval(e1);
     257        Evaluation r2 = eval(e2);
     258
     259        if ( !r1.hasKnownValue ) return false;
     260        if ( !r2.hasKnownValue ) return false;
     261
     262        if ( r1.knownValue != r2.knownValue ) return false;
     263
     264        return true;
     265}
     266
     267static bool exprsPolyCompatible( ast::Expr const * lhs,
     268                ast::Expr const * rhs ) {
     269        type_index const lid = typeid(*lhs);
     270        type_index const rid = typeid(*rhs);
     271        if ( lid != rid ) return false;
     272
     273        if ( exprsPolyCompatibleByStaticValue( lhs, rhs ) ) return true;
     274
     275        if ( type_index(typeid(ast::CastExpr)) == lid ) {
     276                ast::CastExpr const * l = as<ast::CastExpr>(lhs);
     277                ast::CastExpr const * r = as<ast::CastExpr>(rhs);
     278
     279                // inspect casts' target types
     280                if ( !typesPolyCompatible(
     281                        l->result, r->result ) ) return false;
     282
     283                // inspect casts' inner expressions
     284                return exprsPolyCompatible( l->arg, r->arg );
     285
     286        } else if ( type_index(typeid(ast::VariableExpr)) == lid ) {
     287                ast::VariableExpr const * l = as<ast::VariableExpr>(lhs);
     288                ast::VariableExpr const * r = as<ast::VariableExpr>(rhs);
     289
     290                assert(l->var);
     291                assert(r->var);
     292
     293                // conservative: variable exprs match if their declarations are
     294                // represented by the same C++ AST object
     295                return (l->var == r->var);
     296
     297        } else if ( type_index(typeid(ast::SizeofExpr)) == lid ) {
     298                ast::SizeofExpr const * l = as<ast::SizeofExpr>(lhs);
     299                ast::SizeofExpr const * r = as<ast::SizeofExpr>(rhs);
     300
     301                assert((l->type != nullptr) ^ (l->expr != nullptr));
     302                assert((r->type != nullptr) ^ (r->expr != nullptr));
     303                if ( !(l->type && r->type) ) return false;
     304
     305                // mutual recursion with type poly compatibility
     306                return typesPolyCompatible( l->type, r->type );
     307
     308        } else {
     309                // All other forms compare on static value only, done earlier
     310                return false;
     311        }
     312}
     313
    245314bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ) {
    246315        type_index const lid = typeid(*lhs);
     
    256325
    257326        // So remaining types can be examined case by case.
    258         // Recurse through type structure (conditions borrowed from Unify.cpp).
     327        // Recurse through type structure (conditions duplicated from Unify.cpp).
    259328
    260329        if ( type_index(typeid(ast::BasicType)) == lid ) {
     
    280349                ast::ArrayType const * r = as<ast::ArrayType>(rhs);
    281350
    282                 if ( l->isVarLen ) {
    283                         if ( !r->isVarLen ) return false;
    284                 } else {
    285                         if ( r->isVarLen ) return false;
    286 
    287                         auto lc = l->dimension.as<ast::ConstantExpr>();
    288                         auto rc = r->dimension.as<ast::ConstantExpr>();
    289                         if ( lc && rc && lc->intValue() != rc->intValue() ) {
     351                if ( l->isVarLen != r->isVarLen ) return false;
     352                if ( (l->dimension != nullptr) != (r->dimension != nullptr) )
     353                        return false;
     354
     355                if ( l->dimension ) {
     356                        assert( r->dimension );
     357                        // mutual recursion with expression poly compatibility
     358                        if ( !exprsPolyCompatible(l->dimension, r->dimension) )
    290359                                return false;
    291                         }
    292360                }
    293361
Note: See TracChangeset for help on using the changeset viewer.