Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (10 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode? and clean-up.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CommonType.cc

    r790d835 rc6b4432  
    2323#include "AST/Pass.hpp"
    2424#include "AST/Type.hpp"
    25 #include "Common/PassVisitor.h"
    26 #include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
    27 #include "SymTab/Indexer.h"              // for Indexer
    28 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl (ptr...
    29 #include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    30 #include "SynTree/Visitor.h"             // for Visitor
    3125#include "Unify.h"                       // for unifyExact, WidenMode
    3226#include "typeops.h"                     // for isFtype
     
    4135
    4236namespace ResolvExpr {
    43         struct CommonType_old : public WithShortCircuiting {
    44                 CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    45                 Type * get_result() const { return result; }
    46 
    47                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    48 
    49                 void postvisit( VoidType * voidType );
    50                 void postvisit( BasicType * basicType );
    51                 void postvisit( PointerType * pointerType );
    52                 void postvisit( ArrayType * arrayType );
    53                 void postvisit( ReferenceType * refType );
    54                 void postvisit( FunctionType * functionType );
    55                 void postvisit( StructInstType * aggregateUseType );
    56                 void postvisit( UnionInstType * aggregateUseType );
    57                 void postvisit( EnumInstType * aggregateUseType );
    58                 void postvisit( TraitInstType * aggregateUseType );
    59                 void postvisit( TypeInstType * aggregateUseType );
    60                 void postvisit( TupleType * tupleType );
    61                 void postvisit( VarArgsType * varArgsType );
    62                 void postvisit( ZeroType * zeroType );
    63                 void postvisit( OneType * oneType );
    64 
    65           private:
    66                 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer );
    67                 template< typename RefType > void handleRefType( RefType * inst, Type * other );
    68 
    69                 Type * result;
    70                 Type * type2;                           // inherited
    71                 bool widenFirst, widenSecond;
    72                 const SymTab::Indexer &indexer;
    73                 TypeEnvironment &env;
    74                 const OpenVarSet &openVars;
    75         };
    76 
    77         Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
    78                 Type * common = nullptr;
    79                 AssertionSet have, need;
    80                 OpenVarSet newOpen( openVars );
    81                 // need unify to bind type variables
    82                 if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
    83                         PRINT(
    84                                 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    85                         )
    86                         if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
    87                                 PRINT(
    88                                         std::cerr << "widen okay" << std::endl;
    89                                 )
    90                                 common->tq |= t1->tq;
    91                                 common->tq |= t2->tq;
    92                                 return common;
    93                         }
    94                 }
    95                 PRINT(
    96                         std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
    97                 )
    98                 return nullptr;
    99         }
    100 
    101         Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    102                 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    103 
    104                 int depth1 = type1->referenceDepth();
    105                 int depth2 = type2->referenceDepth();
    106                 if ( depth1 > 0 || depth2 > 0 ) {
    107                         int diff = depth1-depth2;
    108                         // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
    109                         // if ( diff > 1 || diff < -1 ) return nullptr;
    110 
    111                         // special case where one type has a reference depth of 1 larger than the other
    112                         if ( diff > 0 || diff < 0 ) {
    113                                 PRINT(
    114                                         std::cerr << "reference depth diff: " << diff << std::endl;
    115                                 )
    116                                 Type * result = nullptr;
    117                                 ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
    118                                 ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
    119                                 if ( diff > 0 ) {
    120                                         // deeper on the left
    121                                         assert( ref1 );
    122                                         result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
    123                                 } else {
    124                                         // deeper on the right
    125                                         assert( ref2 );
    126                                         result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
    127                                 }
    128                                 if ( result && ref1 ) {
    129                                         // formal is reference, so result should be reference
    130                                         PRINT(
    131                                                 std::cerr << "formal is reference; result should be reference" << std::endl;
    132                                         )
    133                                         result = new ReferenceType( ref1->tq, result );
    134                                 }
    135                                 PRINT(
    136                                         std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
    137                                 )
    138                                 return result;
    139                         }
    140                         // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
    141                 }
    142 
    143                 type1->accept( visitor );
    144                 Type * result = visitor.pass.get_result();
    145                 if ( ! result ) {
    146                         // this appears to be handling for opaque type declarations
    147                         if ( widenSecond ) {
    148                                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) {
    149                                         if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) {
    150                                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    151                                                 if ( type->get_base() ) {
    152                                                         Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
    153                                                         AssertionSet have, need;
    154                                                         OpenVarSet newOpen( openVars );
    155                                                         type1->tq = Type::Qualifiers();
    156                                                         type->get_base()->tq = tq1;
    157                                                         if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
    158                                                                 result = type1->clone();
    159                                                                 result->tq = tq1 | tq2;
    160                                                         } // if
    161                                                         type1->tq = tq1;
    162                                                         type->get_base()->tq = Type::Qualifiers();
    163                                                 } // if
    164                                         } // if
    165                                 } // if
    166                         } // if
    167                 } // if
    168 #ifdef DEBUG
    169                 std::cerr << "============= commonType" << std::endl << "type1 is ";
    170                 type1->print( std::cerr );
    171                 std::cerr << " type2 is ";
    172                 type2->print( std::cerr );
    173                 if ( result ) {
    174                         std::cerr << " common type is ";
    175                         result->print( std::cerr );
    176                 } else {
    177                         std::cerr << " no common type";
    178                 } // if
    179                 std::cerr << std::endl;
    180 #endif
    181                 return result;
    182         }
    18337
    18438        // GENERATED START, DO NOT EDIT
     
    488342                "Each basic type kind should have a corresponding row in the combined type matrix"
    489343        );
    490 
    491         CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    492                 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    493         }
    494 
    495         void CommonType_old::postvisit( VoidType * ) {}
    496 
    497         void CommonType_old::postvisit( BasicType * basicType ) {
    498                 if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) {
    499                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ (ast::BasicType::Kind)(int)otherBasic->get_kind() ];
    500                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) {
    501                                 result = new BasicType( basicType->tq | otherBasic->tq, newType );
    502                         } // if
    503                 } else if (  dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    504                         // use signed int in lieu of the enum/zero/one type
    505                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    506                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    507                                 result = new BasicType( basicType->tq | type2->tq, newType );
    508                         } // if
    509                 } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
    510                         const EnumDecl* enumDecl = enumInst->baseEnum;
    511                         if ( const Type* baseType = enumDecl->base ) {
    512                                 result = baseType->clone();
    513                         } else {
    514                                 BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    515                                 if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    516                                         result = new BasicType( basicType->tq | type2->tq, newType );
    517                                 } // if
    518                         }
    519                 }
    520         }
    521 
    522         template< typename Pointer >
    523         void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
    524                 if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
    525                         OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
    526                         if ( entry != openVars.end() ) {
    527                                 AssertionSet need, have;
    528                                 WidenMode widen( widenFirst, widenSecond );
    529                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    530                         }
    531                 }
    532                 result = voidPointer->clone();
    533                 result->tq |= otherPointer->tq;
    534         }
    535 
    536         void CommonType_old::postvisit( PointerType * pointerType ) {
    537                 if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
    538                         // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    539                         if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    540                                 getCommonWithVoidPointer( otherPointer, pointerType );
    541                         } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
    542                                 getCommonWithVoidPointer( pointerType, otherPointer );
    543                         } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
    544                                            && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
    545                                 // std::cerr << "middle case" << std::endl;
    546                                 Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq;
    547                                 pointerType->get_base()->tq = Type::Qualifiers();
    548                                 otherPointer->get_base()->tq = Type::Qualifiers();
    549                                 AssertionSet have, need;
    550                                 OpenVarSet newOpen( openVars );
    551                                 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
    552                                         // std::cerr << "unifyExact success" << std::endl;
    553                                         if ( tq1 < tq2 ) {
    554                                                 result = pointerType->clone();
    555                                         } else {
    556                                                 result = otherPointer->clone();
    557                                         } // if
    558                                         strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
    559                                 } else {
    560                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    561                                 } // if
    562                                 pointerType->get_base()->tq = tq1;
    563                                 otherPointer->get_base()->tq = tq2;
    564                         } // if
    565                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    566                         result = pointerType->clone();
    567                         result->tq |= type2->tq;
    568                 } // if
    569         }
    570 
    571         void CommonType_old::postvisit( ArrayType * ) {}
    572 
    573         void CommonType_old::postvisit( ReferenceType * refType ) {
    574                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
    575                         // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
    576                         // std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl;
    577                         if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
    578                                 getCommonWithVoidPointer( otherRef, refType );
    579                         } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
    580                                 getCommonWithVoidPointer( refType, otherRef );
    581                         } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
    582                                            && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
    583                                 // std::cerr << "middle case" << std::endl;
    584                                 Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq;
    585                                 refType->get_base()->tq = Type::Qualifiers();
    586                                 otherRef->get_base()->tq = Type::Qualifiers();
    587                                 AssertionSet have, need;
    588                                 OpenVarSet newOpen( openVars );
    589                                 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
    590                                         if ( tq1 < tq2 ) {
    591                                                 result = refType->clone();
    592                                         } else {
    593                                                 result = otherRef->clone();
    594                                         } // if
    595                                         strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
    596                                 } else {
    597                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    598                                 } // if
    599                                 refType->get_base()->tq = tq1;
    600                                 otherRef->get_base()->tq = tq2;
    601                         } // if
    602                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    603                         result = refType->clone();
    604                         result->tq |= type2->tq;
    605                 } // if
    606         }
    607 
    608         void CommonType_old::postvisit( FunctionType * ) {}
    609         void CommonType_old::postvisit( StructInstType * ) {}
    610         void CommonType_old::postvisit( UnionInstType * ) {}
    611 
    612         void CommonType_old::postvisit( EnumInstType * enumInstType ) {
    613                 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    614                         // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    615                         result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
    616                 } // if
    617         }
    618 
    619         void CommonType_old::postvisit( TraitInstType * ) {
    620         }
    621 
    622         void CommonType_old::postvisit( TypeInstType * inst ) {
    623                 if ( widenFirst ) {
    624                         const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
    625                         if ( nt ) {
    626                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    627                                 if ( type->get_base() ) {
    628                                         Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
    629                                         AssertionSet have, need;
    630                                         OpenVarSet newOpen( openVars );
    631                                         type2->tq = Type::Qualifiers();
    632                                         type->get_base()->tq = tq1;
    633                                         if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
    634                                                 result = type2->clone();
    635                                                 result->tq = tq1 | tq2;
    636                                         } // if
    637                                         type2->tq = tq2;
    638                                         type->get_base()->tq = Type::Qualifiers();
    639                                 } // if
    640                         } // if
    641                 } // if
    642         }
    643 
    644         void CommonType_old::postvisit( TupleType * ) {}
    645         void CommonType_old::postvisit( VarArgsType * ) {}
    646 
    647         void CommonType_old::postvisit( ZeroType * zeroType ) {
    648                 if ( widenFirst ) {
    649                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    650                                 if ( widenSecond || zeroType->tq <= type2->tq ) {
    651                                         result = type2->clone();
    652                                         result->tq |= zeroType->tq;
    653                                 }
    654                         } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {
    655                                 result = new BasicType( zeroType->tq, BasicType::SignedInt );
    656                                 result->tq |= type2->tq;
    657                         }
    658                 }
    659         }
    660 
    661         void CommonType_old::postvisit( OneType * oneType ) {
    662                 if ( widenFirst ) {
    663                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    664                                 if ( widenSecond || oneType->tq <= type2->tq ) {
    665                                         result = type2->clone();
    666                                         result->tq |= oneType->tq;
    667                                 }
    668                         } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    669                                 result = new BasicType( oneType->tq, BasicType::SignedInt );
    670                                 result->tq |= type2->tq;
    671                         }
    672                 }
    673         }
    674344
    675345        class CommonType_new final : public ast::WithShortCircuiting {
Note: See TracChangeset for help on using the changeset viewer.