Changeset 78a0b88


Ignore:
Timestamp:
Sep 1, 2017, 3:33:25 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
bc3127d
Parents:
e8ccca3 (diff), a01f7c9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Location:
src
Files:
3 added
21 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    re8ccca3 r78a0b88  
    195195                }
    196196
    197                 output << kind;
    198                 if ( aggDecl->get_name() != "" )
    199                         output << aggDecl->get_name();
     197                output << kind << aggDecl->get_name();
    200198
    201199                if ( aggDecl->has_body() ) {
     
    233231                genAttributes( enumDecl->get_attributes() );
    234232
    235                 if ( enumDecl->get_name() != "" )
    236                         output << enumDecl->get_name();
     233                output << enumDecl->get_name();
    237234
    238235                std::list< Declaration* > &memb = enumDecl->get_members();
     
    260257        }
    261258
    262         void CodeGenerator::visit( __attribute__((unused)) TraitDecl * traitDecl ) {}
     259        void CodeGenerator::visit( TraitDecl * traitDecl ) {
     260                assertf( ! genC, "TraitDecl nodes should not reach code generation." );
     261                extension( traitDecl );
     262                handleAggregate( traitDecl, "trait " );
     263        }
    263264
    264265        void CodeGenerator::visit( TypedefDecl * typeDecl ) {
     
    760761                for ( Statement * stmt : stmts ) {
    761762                        updateLocation( stmt );
    762                         output << printLabels( stmt->get_labels() );
     763                        output << indent << printLabels( stmt->get_labels() );
    763764                        if ( i+1 == numStmts ) {
    764765                                // last statement in a statement expression needs to be handled specially -
  • src/CodeGen/Generate.cc

    re8ccca3 r78a0b88  
    2121#include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
    2222#include "GenType.h"                 // for genPrettyType
     23#include "Common/PassVisitor.h"      // for PassVisitor
    2324#include "Parser/LinkageSpec.h"      // for isBuiltin, isGeneratable
    2425#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
     
    2930
    3031namespace CodeGen {
     32        namespace {
     33                /// Removes misc. nodes that should not exist in CodeGen
     34                struct TreeCleaner {
     35                        void visit( CompoundStmt * stmt );
     36
     37                        static bool shouldClean( Declaration * );
     38                };
     39
     40                void cleanTree( std::list< Declaration * > & translationUnit ) {
     41                        PassVisitor<TreeCleaner> cleaner;
     42                        filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
     43                        acceptAll( translationUnit, cleaner );
     44                } // cleanTree
     45        } // namespace
     46
    3147        void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks ) {
     48                cleanTree( translationUnit );
     49
    3250                CodeGen::CodeGenerator cgv( os, pretty, generateC, lineMarks );
    3351                for ( auto & dcl : translationUnit ) {
     
    5270                os << std::endl;
    5371        }
     72
     73        namespace {
     74                void TreeCleaner::visit( CompoundStmt * cstmt ) {
     75                        filter( cstmt->kids, [](Statement * stmt) {
     76                                if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
     77                                        return shouldClean( declStmt->decl );
     78                                }
     79                                return false;
     80                        }, false );
     81                }
     82
     83                bool TreeCleaner::shouldClean( Declaration * decl ) {
     84                        return dynamic_cast< TraitDecl * >( decl );
     85                }
     86        } // namespace
    5487} // namespace CodeGen
    5588
  • src/Common/utility.h

    re8ccca3 r78a0b88  
    172172auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
    173173  return std::copy_if(std::forward<Args>(args)...);
     174}
     175
     176template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
     177void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) {
     178        auto i = begin( container );
     179        while ( i != end( container ) ) {
     180                auto it = next( i );
     181                if ( pred( *i ) ) {
     182                        if ( doDelete ) {
     183                                delete *i;
     184                        } // if
     185                        container.erase( i );
     186                } // if
     187                i = it;
     188        } // while
    174189}
    175190
  • src/GenPoly/Box.cc

    re8ccca3 r78a0b88  
    141141                        virtual StructDecl *mutate( StructDecl *structDecl ) override;
    142142                        virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
     143                        virtual TraitDecl *mutate( TraitDecl *unionDecl ) override;
    143144                        virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
    144145                        virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
     
    216217                  private:
    217218                };
    218 
    219219        } // anonymous namespace
    220220
     
    896896                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
    897897                                bodyStmt = new ExprStmt( noLabels, adapteeApp );
    898 //                      } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
    899898                        } else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
    900899                                // return type T
     
    13521351                }
    13531352
     1353                TraitDecl * Pass2::mutate( TraitDecl *aggDecl ) {
     1354                        return handleAggDecl( aggDecl );
     1355                }
     1356
    13541357                TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
    13551358                        addToTyVarMap( typeDecl, scopeTyVars );
     
    13771380                Type *Pass2::mutate( FunctionType *funcType ) {
    13781381                        scopeTyVars.beginScope();
     1382
    13791383                        makeTyVarMap( funcType, scopeTyVars );
    13801384
     
    15501554                                        // (alloca was previously used, but can't be safely used in loops)
    15511555                                        Type *declType = objectDecl->get_type();
    1552                                         std::string bufName = bufNamer.newName();
    1553                                         ObjectDecl *newBuf = new ObjectDecl( bufName, Type::StorageClasses(), LinkageSpec::C, 0,
     1556                                        ObjectDecl *newBuf = new ObjectDecl( bufNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0,
    15541557                                                new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ),
    1555                                                 true, false, std::list<Attribute*>{ new Attribute( std::string{"aligned"}, std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
     1558                                                true, false, std::list<Attribute*>{ new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
    15561559                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newBuf ) );
    15571560
    15581561                                        delete objectDecl->get_init();
    1559 
    1560                                         objectDecl->set_init( new SingleInit( new NameExpr( bufName ) ) );
     1562                                        objectDecl->set_init( new SingleInit( new VariableExpr( newBuf ) ) );
    15611563                                }
    15621564                        }
  • src/GenPoly/GenPoly.cc

    re8ccca3 r78a0b88  
    336336                                assertf(bparam, "Aggregate parameters should be type expressions");
    337337
    338                                 // xxx - might need to let VoidType be a wildcard here too; could have some voids 
     338                                // xxx - might need to let VoidType be a wildcard here too; could have some voids
    339339                                // stuffed in for dtype-statics.
    340340                                // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
    341341                                if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
    342342                        }
    343                        
     343
    344344                        return true;
    345345                }
     
    350350                // polymorphic types always match
    351351                if ( aid == type_index{typeid(TypeInstType)} ) return true;
    352                
     352
    353353                type_index bid{ typeid(*b) };
    354354                // polymorphic types always match
    355355                if ( bid == type_index{typeid(TypeInstType)} ) return true;
    356                
     356
    357357                // can't match otherwise if different types
    358358                if ( aid != bid ) return false;
     
    377377                                ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
    378378                                ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
    379                                 if ( ad && bd 
     379                                if ( ad && bd
    380380                                                && ad->get_constant()->get_value() != bd->get_constant()->get_value() )
    381381                                        return false;
     
    433433
    434434        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
     435                // xxx - should this actually be insert?
    435436                tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
    436437        }
  • src/Parser/ExpressionNode.cc

    re8ccca3 r78a0b88  
    360360Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
    361361        std::list< Expression * > args;
    362         args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx
     362        args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
    363363        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    364364} // build_unary_ptr
  • src/Parser/StatementNode.cc

    re8ccca3 r78a0b88  
    9999        } // if
    100100
    101         Expression * cond = ctl->condition ? maybeMoveBuild< Expression >(ctl->condition) : new VariableExpr( dynamic_cast<DeclarationWithType *>( dynamic_cast<DeclStmt *>( init.back() )->decl ) );
     101        Expression * cond = nullptr;
     102        if ( ctl->condition ) {
     103                // compare the provided condition against 0
     104                cond =  notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
     105        } else {
     106                for ( Statement * stmt : init ) {
     107                        // build the && of all of the declared variables compared against 0
     108                        DeclStmt * declStmt = safe_dynamic_cast< DeclStmt * >( stmt );
     109                        DeclarationWithType * dwt = safe_dynamic_cast< DeclarationWithType * >( declStmt->decl );
     110                        Expression * nze = notZeroExpr( new VariableExpr( dwt ) );
     111                        cond = cond ? new LogicalExpr( cond, nze, true ) : nze;
     112                }
     113        }
    102114        delete ctl;
    103         return new IfStmt( noLabels, notZeroExpr( cond ), thenb, elseb, init );
     115        return new IfStmt( noLabels, cond, thenb, elseb, init );
    104116}
    105117
  • src/ResolvExpr/AlternativeFinder.cc

    re8ccca3 r78a0b88  
    749749                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    750750                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    751                                                 referenceToRvalueConversion( func->expr );
     751                                                Alternative newFunc( *func );
     752                                                referenceToRvalueConversion( newFunc.expr );
    752753                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    753754                                                        // XXX
    754755                                                        //Designators::check_alternative( function, *actualAlt );
    755                                                         makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     756                                                        makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
    756757                                                }
    757758                                        }
    758759                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    759                                         referenceToRvalueConversion( func->expr );
    760760                                        EqvClass eqvClass;
    761761                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    762762                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     763                                                        Alternative newFunc( *func );
     764                                                        referenceToRvalueConversion( newFunc.expr );
    763765                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    764                                                                 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     766                                                                makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
    765767                                                        } // for
    766768                                                } // if
     
    773775                                        if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    774776                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    775                                                         referenceToRvalueConversion( funcOp->expr );
     777                                                        Alternative newFunc( *funcOp );
     778                                                        referenceToRvalueConversion( newFunc.expr );
    776779                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    777780                                                                AltList currentAlt;
    778781                                                                currentAlt.push_back( *func );
    779782                                                                currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
    780                                                                 makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
     783                                                                makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) );
    781784                                                        } // for
    782785                                                } // if
  • src/ResolvExpr/RenameVars.cc

    re8ccca3 r78a0b88  
    8888                typeBefore( aggregateUseType );
    8989                acceptAll( aggregateUseType->get_parameters(), *this );
    90                 acceptAll( aggregateUseType->get_members(), *this );
    9190                typeAfter( aggregateUseType );
    9291        }
  • src/ResolvExpr/TypeEnvironment.cc

    re8ccca3 r78a0b88  
    2525
    2626namespace ResolvExpr {
    27         // adding this comparison operator significantly improves assertion resolution run time for
    28         // some cases. The current resolution algorithm's speed partially depends on the order of
    29         // assertions. Assertions which have fewer possible matches should appear before
    30         // assertions which have more possible matches. This seems to imply that this could
    31         // be further improved by providing an indexer as an additional argument and ordering based
    32         // on the number of matches of the same kind (object, function) for the names of the
    33         // declarations.
    34         //
    35         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    36         bool AssertCompare::operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
    37                         // Objects are always less than functions
    38                         if ( ObjectDecl * objectDecl1 = dynamic_cast< ObjectDecl * >( d1 ) ) {
    39                                 if ( ObjectDecl * objectDecl2 = dynamic_cast< ObjectDecl * >( d2 ) ) {
    40                                         // objects are ordered by name then type pointer, in that order
    41                                         int cmp = objectDecl1->get_name().compare( objectDecl2->get_name() );
    42                                         return cmp < 0 ||
    43                                                 ( cmp == 0 && objectDecl1->get_type() < objectDecl2->get_type() );
    44                                 } else {
    45                                         return true;
    46                                 }
    47                         } else if ( FunctionDecl * funcDecl1 = dynamic_cast< FunctionDecl * >( d1 ) ) {
    48                                 if ( FunctionDecl * funcDecl2 = dynamic_cast< FunctionDecl * >( d2 ) ) {
    49                                         // functions are ordered by name, # parameters, # returnVals, type pointer in that order
    50                                         FunctionType * ftype1 = funcDecl1->get_functionType();
    51                                         FunctionType * ftype2 = funcDecl2->get_functionType();
    52                                         int numThings1 = ftype1->get_parameters().size() + ftype1->get_returnVals().size();
    53                                         int numThings2 = ftype2->get_parameters().size() + ftype2->get_returnVals().size();
    54                                         if ( numThings1 < numThings2 ) return true;
    55                                         if ( numThings1 > numThings2 ) return false;
    56 
    57                                         // if ( ftype1->get_parameters().size() < ftype2->get_parameters().size() ) return true;
    58                                         // else if ( ftype1->get_parameters().size() > ftype2->get_parameters().size() ) return false;
    59                                         // // same number of parameters
    60                                         // if ( ftype1->get_returnVals().size() < ftype2->get_returnVals().size() ) return true;
    61                                         // else if ( ftype1->get_returnVals().size() > ftype2->get_returnVals().size() ) return false;
    62                                         // same number of return vals
    63                                         // int cmp = funcDecl1->get_name().compare( funcDecl2->get_name() );
    64                                         // if ( cmp < 0 ) return true;
    65                                         // else if ( cmp > 0 ) return false;
    66                                         // // same name
    67                                         return ftype1 < ftype2;
    68                                 } else {
    69                                         return false;
    70                                 }
    71                         } else {
    72                                 assert( false );
    73                         }
    74                 }
    75 
    7627        void printAssertionSet( const AssertionSet &assertions, std::ostream &os, int indent ) {
    7728                for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) {
  • src/ResolvExpr/TypeEnvironment.h

    re8ccca3 r78a0b88  
    2828
    2929namespace ResolvExpr {
     30        // adding this comparison operator significantly improves assertion resolution run time for
     31        // some cases. The current resolution algorithm's speed partially depends on the order of
     32        // assertions. Assertions which have fewer possible matches should appear before
     33        // assertions which have more possible matches. This seems to imply that this could
     34        // be further improved by providing an indexer as an additional argument and ordering based
     35        // on the number of matches of the same kind (object, function) for the names of the
     36        // declarations.
     37        //
     38        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    3039        struct AssertCompare {
    31                 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const;
     40                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     41                        int cmp = d1->get_name().compare( d2->get_name() );
     42                        return cmp < 0 ||
     43                                ( cmp == 0 && d1->get_type() < d2->get_type() );
     44                }
    3245        };
    3346        struct AssertionSetValue {
  • src/SymTab/Indexer.cc

    re8ccca3 r78a0b88  
    554554
    555555
    556         void Indexer::visit( TraitInstType *contextInst ) {
    557                 acceptAll( contextInst->get_parameters(), *this );
    558                 acceptAll( contextInst->get_members(), *this );
     556        void Indexer::visit( TraitInstType *traitInst ) {
     557                acceptAll( traitInst->get_parameters(), *this );
    559558        }
    560559
  • src/SymTab/Validate.cc

    re8ccca3 r78a0b88  
    127127          public:
    128128                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    129                 using Parent::visit;
     129                using Parent::visit;
     130                void visit( TypeInstType *typeInst ) final;
     131
    130132                void visit( EnumInstType *enumInst ) final;
    131133                void visit( StructInstType *structInst ) final;
    132134                void visit( UnionInstType *unionInst ) final;
    133                 void visit( TraitInstType *contextInst ) final;
     135                void visit( TraitInstType *traitInst ) final;
     136
    134137                void visit( EnumDecl *enumDecl ) final;
    135138                void visit( StructDecl *structDecl ) final;
    136139                void visit( UnionDecl *unionDecl ) final;
    137                 void visit( TypeInstType *typeInst ) final;
     140                void visit( TraitDecl * traitDecl ) final;
     141
    138142          private:
    139143                const Indexer *indexer;
     
    287291
    288292        HoistStruct::HoistStruct() : inStruct( false ) {
    289         }
    290 
    291         void filter( std::list< Declaration * > &declList, bool (*pred)( Declaration * ), bool doDelete ) {
    292                 std::list< Declaration * >::iterator i = declList.begin();
    293                 while ( i != declList.end() ) {
    294                         std::list< Declaration * >::iterator next = i;
    295                         ++next;
    296                         if ( pred( *i ) ) {
    297                                 if ( doDelete ) {
    298                                         delete *i;
    299                                 } // if
    300                                 declList.erase( i );
    301                         } // if
    302                         i = next;
    303                 } // while
    304293        }
    305294
     
    453442        }
    454443
    455         void LinkReferenceToTypes::visit( TraitInstType *traitInst ) {
     444        template< typename Decl >
     445        void normalizeAssertions( std::list< Decl * > & assertions ) {
     446                // ensure no duplicate trait members after the clone
     447                auto pred = [](Decl * d1, Decl * d2) {
     448                        // only care if they're equal
     449                        DeclarationWithType * dwt1 = dynamic_cast<DeclarationWithType *>( d1 );
     450                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
     451                        if ( dwt1 && dwt2 ) {
     452                                if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     453                                        // std::cerr << "=========== equal:" << std::endl;
     454                                        // std::cerr << "d1: " << d1 << std::endl;
     455                                        // std::cerr << "d2: " << d2 << std::endl;
     456                                        return false;
     457                                }
     458                        }
     459                        return d1 < d2;
     460                };
     461                std::set<Decl *, decltype(pred)> unique_members( assertions.begin(), assertions.end(), pred );
     462                // if ( unique_members.size() != assertions.size() ) {
     463                //      std::cerr << "============different" << std::endl;
     464                //      std::cerr << unique_members.size() << " " << assertions.size() << std::endl;
     465                // }
     466
     467                std::list< Decl * > order;
     468                order.splice( order.end(), assertions );
     469                std::copy_if( order.begin(), order.end(), back_inserter( assertions ), [&]( Decl * decl ) {
     470                        return unique_members.count( decl );
     471                });
     472        }
     473
     474        // expand assertions from trait instance, performing the appropriate type variable substitutions
     475        template< typename Iterator >
     476        void expandAssertions( TraitInstType * inst, Iterator out ) {
     477                assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
     478                std::list< DeclarationWithType * > asserts;
     479                for ( Declaration * decl : inst->baseTrait->members ) {
     480                        asserts.push_back( safe_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
     481                }
     482                // substitute trait decl parameters for instance parameters
     483                applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
     484        }
     485
     486        void LinkReferenceToTypes::visit( TraitDecl * traitDecl ) {
     487                Parent::visit( traitDecl );
     488
     489                if ( traitDecl->name == "sized" ) {
     490                        // "sized" is a special trait - flick the sized status on for the type variable
     491                        assertf( traitDecl->parameters.size() == 1, "Built-in trait 'sized' has incorrect number of parameters: %zd", traitDecl->parameters.size() );
     492                        TypeDecl * td = traitDecl->parameters.front();
     493                        td->set_sized( true );
     494                }
     495
     496                // move assertions from type parameters into the body of the trait
     497                for ( TypeDecl * td : traitDecl->parameters ) {
     498                        for ( DeclarationWithType * assert : td->assertions ) {
     499                                if ( TraitInstType * inst = dynamic_cast< TraitInstType * >( assert->get_type() ) ) {
     500                                        expandAssertions( inst, back_inserter( traitDecl->members ) );
     501                                } else {
     502                                        traitDecl->members.push_back( assert->clone() );
     503                                }
     504                        }
     505                        deleteAll( td->assertions );
     506                        td->assertions.clear();
     507                } // for
     508        }
     509
     510        void LinkReferenceToTypes::visit( TraitInstType * traitInst ) {
    456511                Parent::visit( traitInst );
    457                 if ( traitInst->get_name() == "sized" ) {
    458                         // "sized" is a special trait with no members - just flick the sized status on for the type variable
    459                         if ( traitInst->get_parameters().size() != 1 ) {
    460                                 throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    461                         }
    462                         TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( traitInst->get_parameters().front() );
    463                         TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
    464                         TypeDecl * decl = inst->get_baseType();
    465                         decl->set_sized( true );
    466                         // since "sized" is special, the next few steps don't apply
    467                         return;
    468                 }
    469 
    470512                // handle other traits
    471                 TraitDecl *traitDecl = indexer->lookupTrait( traitInst->get_name() );
     513                TraitDecl *traitDecl = indexer->lookupTrait( traitInst->name );
    472514                if ( ! traitDecl ) {
    473                         throw SemanticError( "use of undeclared trait " + traitInst->get_name() );
     515                        throw SemanticError( "use of undeclared trait " + traitInst->name );
    474516                } // if
    475517                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
    476518                        throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    477519                } // if
    478 
    479                 for ( TypeDecl * td : traitDecl->get_parameters() ) {
    480                         for ( DeclarationWithType * assert : td->get_assertions() ) {
    481                                 traitInst->get_members().push_back( assert->clone() );
    482                         } // for
    483                 } // for
    484 
    485                 // need to clone members of the trait for ownership purposes
    486                 std::list< Declaration * > members;
    487                 std::transform( traitDecl->get_members().begin(), traitDecl->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
    488 
    489                 applySubstitution( traitDecl->get_parameters().begin(), traitDecl->get_parameters().end(), traitInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( traitInst->get_members() ) );
     520                traitInst->baseTrait = traitDecl;
    490521
    491522                // need to carry over the 'sized' status of each decl in the instance
     
    498529                        }
    499530                }
     531                // normalizeAssertions( traitInst->members );
    500532        }
    501533
     
    561593        void forallFixer( Type * func ) {
    562594                for ( TypeDecl * type : func->get_forall() ) {
    563                         std::list< DeclarationWithType * > toBeDone, nextRound;
    564                         toBeDone.splice( toBeDone.end(), type->get_assertions() );
    565                         while ( ! toBeDone.empty() ) {
    566                                 for ( DeclarationWithType * assertion : toBeDone ) {
    567                                         if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
    568                                                 // expand trait instance into all of its members
    569                                                 for ( Declaration * member : traitInst->get_members() ) {
    570                                                         DeclarationWithType *dwt = safe_dynamic_cast< DeclarationWithType * >( member );
    571                                                         nextRound.push_back( dwt->clone() );
    572                                                 }
    573                                                 delete traitInst;
    574                                         } else {
    575                                                 // pass assertion through
    576                                                 FixFunction fixer;
    577                                                 assertion = assertion->acceptMutator( fixer );
    578                                                 if ( fixer.get_isVoid() ) {
    579                                                         throw SemanticError( "invalid type void in assertion of function ", func );
    580                                                 }
    581                                                 type->get_assertions().push_back( assertion );
    582                                         } // if
    583                                 } // for
    584                                 toBeDone.clear();
    585                                 toBeDone.splice( toBeDone.end(), nextRound );
    586                         } // while
     595                        std::list< DeclarationWithType * > asserts;
     596                        asserts.splice( asserts.end(), type->assertions );
     597                        // expand trait instances into their members
     598                        for ( DeclarationWithType * assertion : asserts ) {
     599                                if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     600                                        // expand trait instance into all of its members
     601                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     602                                        delete traitInst;
     603                                } else {
     604                                        // pass other assertions through
     605                                        type->assertions.push_back( assertion );
     606                                } // if
     607                        } // for
     608                        // apply FixFunction to every assertion to check for invalid void type
     609                        for ( DeclarationWithType *& assertion : type->assertions ) {
     610                                FixFunction fixer;
     611                                assertion = assertion->acceptMutator( fixer );
     612                                if ( fixer.get_isVoid() ) {
     613                                        throw SemanticError( "invalid type void in assertion of function ", func );
     614                                } // if
     615                        } // for
     616                        // normalizeAssertions( type->assertions );
    587617                } // for
    588618        }
     
    752782                CompoundStmt *ret = Mutator::mutate( compoundStmt );
    753783                scopeLevel -= 1;
    754                 std::list< Statement * >::iterator i = compoundStmt->get_kids().begin();
    755                 while ( i != compoundStmt->get_kids().end() ) {
    756                         std::list< Statement * >::iterator next = i+1;
    757                         if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( *i ) ) {
     784                // remove and delete decl stmts
     785                filter( compoundStmt->kids, [](Statement * stmt) {
     786                        if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
    758787                                if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
    759                                         delete *i;
    760                                         compoundStmt->get_kids().erase( i );
     788                                        return true;
    761789                                } // if
    762790                        } // if
    763                         i = next;
    764                 } // while
     791                        return false;
     792                }, true);
    765793                typedefNames.endScope();
    766794                return ret;
     
    771799        template<typename AggDecl>
    772800        AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
    773                 std::list<Declaration *>::iterator it = aggDecl->get_members().begin();
    774                 for ( ; it != aggDecl->get_members().end(); ) {
    775                         std::list< Declaration * >::iterator next = it+1;
    776                         if ( dynamic_cast< TypedefDecl * >( *it ) ) {
    777                                 delete *it;
    778                                 aggDecl->get_members().erase( it );
    779                         } // if
    780                         it = next;
    781                 }
     801                filter( aggDecl->members, isTypedef, true );
    782802                return aggDecl;
    783803        }
  • src/SynTree/Mutator.cc

    re8ccca3 r78a0b88  
    538538Type * Mutator::mutate( TraitInstType *aggregateUseType ) {
    539539        handleReferenceToType( aggregateUseType );
    540         mutateAll( aggregateUseType->get_members(), *this );
    541540        return aggregateUseType;
    542541}
  • src/SynTree/ReferenceToType.cc

    re8ccca3 r78a0b88  
    132132std::string TraitInstType::typeString() const { return "trait"; }
    133133
    134 TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ) {
    135         cloneAll( other.members, members );
     134TraitInstType::TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes ) : Parent( tq, baseTrait->name, attributes ), baseTrait( baseTrait ) {}
     135
     136TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ), baseTrait( other.baseTrait ) {
    136137}
    137138
    138139TraitInstType::~TraitInstType() {
    139         deleteAll( members );
    140140}
    141141
  • src/SynTree/Type.h

    re8ccca3 r78a0b88  
    471471        typedef ReferenceToType Parent;
    472472  public:
    473         // this member is filled in by the validate pass, which instantiates the members of the correponding
    474         // aggregate with the actual type parameters specified for this use of the context
    475         std::list< Declaration* > members;
    476 
    477         TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     473        // this decl is not "owned" by the trait inst; it is merely a pointer to elsewhere in the tree,
     474        // where the trait used in this type is actually defined
     475        TraitDecl * baseTrait = nullptr;
     476
     477        TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {}
     478        TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    478479        TraitInstType( const TraitInstType & other );
    479480        ~TraitInstType();
    480 
    481         std::list< Declaration* >& get_members() { return members; }
    482481
    483482        virtual bool isComplete() const;
  • src/SynTree/TypeSubstitution.h

    re8ccca3 r78a0b88  
    177177void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
    178178        TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
    179         for ( std::list< Declaration* >::iterator i = memberBegin; i != memberEnd; ++i ) {
     179        for ( auto i = memberBegin; i != memberEnd; ++i ) {
    180180                sub.apply( *i );
    181181                *out++ = *i;
  • src/SynTree/Visitor.cc

    re8ccca3 r78a0b88  
    429429void Visitor::visit( TraitInstType *aggregateUseType ) {
    430430        handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) );
    431         acceptAll( aggregateUseType->get_members(), *this );
    432431}
    433432
  • src/prelude/prelude.cf

    re8ccca3 r78a0b88  
    1414
    1515// Section numbers from: http://plg.uwaterloo.ca/~cforall/refrat.pdf
     16
     17// ------------------------------------------------------------
     18//
     19// Section 6.7.11 Trait Declarations
     20// Note: the sized trait is used in declarations later in this
     21// file, so it must be out of order.
     22//
     23// ------------------------------------------------------------
     24
     25trait sized(dtype T) {};
    1626
    1727// ------------------------------------------------------------
  • src/tests/.expect/ifcond.txt

    re8ccca3 r78a0b88  
    11x != 0 correct
    2 x != 0 && y == 0 incorrect
     2x != 0 && y != 0 correct
    33x == y correct
  • src/tests/ifcond.c

    re8ccca3 r78a0b88  
    1 // 
     1//
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // ifcond.c -- 
    8 // 
     6//
     7// ifcond.c --
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Aug 26 10:13:11 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Aug 30 07:55:24 2017
    13 // Update Count     : 13
    14 // 
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Fri Sep 01 15:22:19 2017
     13// Update Count     : 14
     14//
    1515
    16 #include<fstream>
     16#include <fstream>
    1717
    1818int f( int r ) { return r; }
     
    2727        } // if
    2828
    29         if ( int x = 4, y = 0 ) {                                                       // FIXME && distribution
     29        if ( int x = 4, y = 0 ) {
     30                sout | "x != 0 && y != 0 incorrect" | endl;
     31        } else if ( int x = 4, y = 1 ) {
    3032                sout | "x != 0 && y != 0 correct" | endl;
    31     } else {
    32                 sout | "x != 0 && y == 0 incorrect" | endl;
     33        } else {
     34                sout | "x == 0 || y == 0 incorrect" | endl;
    3335        } // if
    3436
Note: See TracChangeset for help on using the changeset viewer.