Changes in / [395fc37:6f95000]


Ignore:
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    r395fc37 r6f95000  
    4040\newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}\xspace} % CC symbolic name
    4141\newcommand{\CCeleven}{\rm C\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
    42 \newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17\xspace} % C++17 symbolic name
    4342\newcommand{\Celeven}{C11\xspace}               % C11 symbolic name
    4443\newcommand{\Csharp}{C\raisebox{0.4ex}{\#}\xspace}      % C# symbolic name
  • src/GenPoly/Specialize.cc

    r395fc37 r6f95000  
    7777        }
    7878
    79         /// True if both types have the same structure, but not necessarily the same types.
    80         /// That is, either both types are tuple types with the same size (recursively), or
    81         /// both are not tuple types.
    82         bool matchingTupleStructure( Type * t1, Type * t2 ) {
    83                 TupleType * tuple1 = dynamic_cast< TupleType * >( t1 );
    84                 TupleType * tuple2 = dynamic_cast< TupleType * >( t2 );
    85                 if ( tuple1 && tuple2 ) {
    86                         if ( tuple1->size() != tuple2->size() ) return false;
    87                         for ( auto types : group_iterate( tuple1->get_types(), tuple2->get_types() ) ) {
    88                                 if ( ! matchingTupleStructure( std::get<0>( types ), std::get<1>( types ) ) ) return false;
    89                         }
    90                         return true;
    91                 } else if ( ! tuple1 && ! tuple2 ) return true;
    92                 return false;
    93         }
    94 
    9579        bool needsTupleSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    96                 // Needs tuple specialization if the structure of the formal type and actual type do not match.
    97                 // This is the case if the formal type has ttype polymorphism, or if the structure  of tuple types
    98                 // between the function do not match exactly.
    99                 if ( FunctionType * fftype = getFunctionType( formalType ) ) {
    100                         if ( fftype->isTtype() ) return true;
    101                         FunctionType * aftype = getFunctionType( actualType );
    102                         assertf( aftype, "formal type is a function type, but actual type is not." );
    103                         if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true;
    104                         for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) {
    105                                 DeclarationWithType * formal = std::get<0>(params);
    106                                 DeclarationWithType * actual = std::get<1>(params);
    107                                 if ( ! matchingTupleStructure( formal->get_type(), actual->get_type() ) ) return true;
    108                         }
     80                if ( FunctionType * ftype = getFunctionType( formalType ) ) {
     81                        return ftype->isTtype();
    10982                }
    11083                return false;
     
    137110        }
    138111
    139         /// restructures the arguments to match the structure of the formal parameters of the actual function.
    140         /// [begin, end) are the exploded arguments.
    141         template< typename Iterator, typename OutIterator >
    142         void structureArg( Type * type, Iterator & begin, Iterator end, OutIterator out ) {
    143                 if ( TupleType * tuple = dynamic_cast< TupleType * >( type ) ) {
     112        /// restructures arg to match the structure of a single formal parameter. Assumes that atomic types are compatible (as the Resolver should have ensured this)
     113        template< typename OutIterator >
     114        void matchOneFormal( Expression * arg, unsigned & idx, Type * formal, OutIterator out ) {
     115                if ( TupleType * tupleType = dynamic_cast< TupleType * >( formal ) ) {
    144116                        std::list< Expression * > exprs;
    145                         for ( Type * t : *tuple ) {
    146                                 structureArg( t, begin, end, back_inserter( exprs ) );
     117                        for ( Type * t : *tupleType ) {
     118                                matchOneFormal( arg, idx, t, back_inserter( exprs ) );
    147119                        }
    148120                        *out++ = new TupleExpr( exprs );
    149121                } else {
    150                         assertf( begin != end, "reached the end of the arguments while structuring" );
    151                         *out++ = *begin++;
    152                 }
    153         }
    154 
    155         /// explode assuming simple cases: either type is pure tuple (but not tuple expr) or type is non-tuple.
    156         template< typename OutputIterator >
    157         void explodeSimple( Expression * expr, OutputIterator out ) {
    158                 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( expr->get_result() ) ) {
    159                         // tuple type, recursively index into its components
    160                         for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
    161                                 explodeSimple( new TupleIndexExpr( expr->clone(), i ), out );
     122                        *out++ = new TupleIndexExpr( arg->clone(), idx++ );
     123                }
     124        }
     125
     126        /// restructures the ttype argument to match the structure of the formal parameters of the actual function.
     127        /// [begin, end) are the formal parameters.
     128        /// args is the list of arguments currently given to the actual function, the last of which needs to be restructured.
     129        template< typename Iterator, typename OutIterator >
     130        void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) {
     131                if ( Tuples::isTtype( last->get_result() ) ) {
     132                        *out++ = last;
     133                } else {
     134                        // safe_dynamic_cast for the assertion
     135                        safe_dynamic_cast< TupleType * >( last->get_result() );
     136                        unsigned idx = 0;
     137                        for ( ; begin != end; ++begin ) {
     138                                DeclarationWithType * formal = *begin;
     139                                Type * formalType = formal->get_type();
     140                                matchOneFormal( last, idx, formalType, out );
    162141                        }
    163                         delete expr;
    164                 } else {
    165                         // non-tuple type - output a clone of the expression
    166                         *out++ = expr;
     142                        delete last;
    167143                }
    168144        }
     
    197173                std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
    198174                std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
    199 
    200                 std::list< Expression * > args;
     175                std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin();
     176                std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end();
     177
    201178                for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) {
    202                         // name each thunk parameter and explode it - these are then threaded back into the actual function call.
     179                        // walk the parameters to the actual function alongside the parameters to the thunk to find the location where the ttype parameter begins to satisfy parameters in the actual function.
    203180                        param->set_name( paramNamer.newName() );
    204                         explodeSimple( new VariableExpr( param ), back_inserter( args ) );
    205                 }
    206 
    207                 // walk parameters to the actual function alongside the exploded thunk parameters and restructure the arguments to match the actual parameters.
    208                 std::list< Expression * >::iterator argBegin = args.begin(), argEnd = args.end();
    209                 for ( ; actualBegin != actualEnd; ++actualBegin ) {
    210                         structureArg( (*actualBegin)->get_type(), argBegin, argEnd, back_inserter( appExpr->get_args() ) );
    211                 }
    212 
     181                        assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" );
     182                        if ( Tuples::isTtype((*formalBegin)->get_type()) ) {
     183                                fixLastArg( new VariableExpr( param ), actualBegin, actualEnd, back_inserter( appExpr->get_args() ) );
     184                                break;
     185                        }
     186                        assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" );
     187                        ++actualBegin;
     188                        ++formalBegin;
     189
     190                        appExpr->get_args().push_back( new VariableExpr( param ) );
     191                } // for
    213192                appExpr->set_env( maybeClone( env ) );
    214193                if ( inferParams ) {
  • src/InitTweak/GenInit.cc

    r395fc37 r6f95000  
    218218
    219219        bool CtorDtor::isManaged( Type * type ) const {
    220                 // need to clear and reset qualifiers when determining if a type is managed
    221                 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
    222                 type->get_qualifiers() = Type::Qualifiers();
    223220                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    224221                        // tuple is also managed if any of its components are managed
  • src/Parser/parser.yy

    r395fc37 r6f95000  
    412412                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_REALFRACTIONconstant( *$2 ) ) ); }
    413413        | postfix_expression ARROW no_attr_identifier
    414                 {
    415                         $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) );
    416                 }
     414                { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
    417415        | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
    418416                        { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
    419         | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    420                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
    421417        | postfix_expression ICR
    422418                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
  • src/ResolvExpr/Resolver.cc

    r395fc37 r6f95000  
    240240                functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
    241241                Parent::visit( functionDecl );
    242 
    243                 // default value expressions have an environment which shouldn't be there and trips up later passes.
    244                 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    245                 // see how it's useful.
    246                 for ( Declaration * d : functionDecl->get_functionType()->get_parameters() ) {
    247                         if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
    248                                 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->get_init() ) ) {
    249                                         delete init->get_value()->get_env();
    250                                         init->get_value()->set_env( nullptr );
    251                                 }
    252                         }
    253                 }
    254242        }
    255243
  • src/SymTab/Autogen.cc

    r395fc37 r6f95000  
    151151        bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
    152152                for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
    153                         if ( param->isComplete() ) return true;
     153                        if ( param->get_kind() == TypeDecl::Any ) return true;
    154154                }
    155155                return false;
  • src/SymTab/Indexer.cc

    r395fc37 r6f95000  
    119119                                FunctionDecl * decl;
    120120                                bool isUserDefinedFunc; // properties for this particular decl
    121                                 bool isDefaultCtor;
    122                                 bool isDtor;
     121                                bool isDefaultFunc;
    123122                                bool isCopyFunc;
    124123                        };
    125124                        // properties for this type
    126                         bool userDefinedFunc = false; // any user-defined function found
    127                         bool userDefinedCtor = false; // any user-defined constructor found
    128                         bool userDefinedDtor = false; // any user-defined destructor found
    129                         bool userDefinedCopyFunc = false; // user-defined copy ctor found
     125                        bool userDefinedFunc = false; // any user defined function found
     126                        bool userDefinedDefaultFunc = false; // user defined default ctor found
     127                        bool userDefinedCopyFunc = false; // user defined copy ctor found
    130128                        std::list< DeclBall > decls;
    131129
     
    134132                        ValueType & operator+=( FunctionDecl * function ) {
    135133                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
    136                                 bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
    137                                 bool isDtor = InitTweak::isDestructor( function );
     134                                bool isDefaultFunc = function->get_functionType()->get_parameters().size() == 1;
    138135                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
    139                                 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
     136                                decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultFunc, isCopyFunc } );
    140137                                userDefinedFunc = userDefinedFunc || isUserDefinedFunc;
    141                                 userDefinedCtor = userDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
    142                                 userDefinedDtor = userDefinedDtor || (isUserDefinedFunc && isDtor);
     138                                userDefinedDefaultFunc = userDefinedDefaultFunc || (isUserDefinedFunc && isDefaultFunc);
    143139                                userDefinedCopyFunc = userDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    144140                                return *this;
     
    167163                // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
    168164                // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
    169                 // If the user defines any ctor then the generated default ctor should not be seen.
    170165                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    171166                        ValueType & val = pair.second;
    172167                        for ( ValueType::DeclBall ball : val.decls ) {
    173                                 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedCtor && ball.isDefaultCtor) || (! val.userDefinedCopyFunc && ball.isCopyFunc) || (! val.userDefinedDtor && ball.isDtor) ) {
     168                                if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedDefaultFunc && ball.isDefaultFunc) || (! val.userDefinedCopyFunc && ball.isCopyFunc) ) {
    174169                                        // decl conforms to the rules described above, so it should be seen by the requester
    175170                                        out.push_back( ball.decl );
  • src/SymTab/Validate.cc

    r395fc37 r6f95000  
    224224                HoistStruct::hoistStruct( translationUnit );
    225225                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    226                 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    227226                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
    228227                acceptAll( translationUnit, epc );
     228                acceptAll( translationUnit, lrt );
    229229                ReturnChecker::checkFunctionReturns( translationUnit );
    230230                compoundliteral.mutateDeclarationList( translationUnit );
     
    840840                assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %d", functionDecl->get_name().c_str(), retVals.size() );
    841841                if ( retVals.size() == 1 ) {
    842                         // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging).
    843                         // ensure other return values have a name.
     842                        // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging)
     843                        // ensure other return values have a name
    844844                        DeclarationWithType * ret = retVals.front();
    845845                        if ( ret->get_name() == "" ) {
  • src/SynTree/TypeDecl.cc

    r395fc37 r6f95000  
    2525
    2626std::string TypeDecl::typeString() const {
    27         static const std::string kindNames[] = { "type", "incomplete type", "function type", "tuple type" };
    28         return (kind != Any && isComplete() ? "sized " : "") + kindNames[ kind ];
     27        static const char *kindNames[] = { "type", "incomplete type", "function type", "tuple type" };
     28        return kindNames[ kind ];
    2929}
    3030
  • src/tests/.expect/tuplePolymorphism.txt

    r395fc37 r6f95000  
    33123 999.123 456
    44246 1998.25 912
    5 1.21 x 10.21 1111 v 54385938 1111 v 54385938
  • src/tests/memberCtors.c

    r395fc37 r6f95000  
    3030  WrappedInt x, y, z;
    3131};
    32 
    33 void ?{}(A * a) {
    34   // currently must define default ctor, since there's no "= default" syntax
    35 }
    3632
    3733void ?{}(A * a, int x) {
  • src/tests/tuplePolymorphism.c

    r395fc37 r6f95000  
    1414//
    1515
    16 // packed is needed so that structs are not passed with the same alignment as function arguments
    17 __attribute__((packed)) struct A {
    18   double x;
    19   char y;
    20   double z;
    21 };
    22 
    23 __attribute__((packed)) struct B {
    24   long long x;
    25   char y;
    26   long long z;
    27 };
    28 
    29 // ensure that f is a viable candidate for g, even though its parameter structure does not exactly match
    30 [A] f([A, B] x, B y) { printf("%g %c %g %lld %c %lld %lld %c %lld\n", x.0.[x,y,z], x.1.[x,y,z], y.[x,y,z]); return x.0; }
    31 forall(otype T, otype U | { T f(T, U, U); })
    32 void g(T x, U y) { f(x, y, y); }
    33 
    34 // add two triples
    3516forall(otype T | { T ?+?(T, T); })
    3617[T, T, T] ?+?([T, T, T] x, [T, T, T] y) {
     
    5940  [x1, x2, x3] = zzz+zzz;
    6041  printf("%d %g %d\n", x1, x2, x3);
    61 
    62   // ensure non-matching assertions are specialized correctly
    63   g((A){ 1.21, 'x', 10.21}, (B){ 1111LL, 'v', 54385938LL });
    6442}
    6543
Note: See TracChangeset for help on using the changeset viewer.