Changes in / [395fc37:6f95000]
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
r395fc37 r6f95000 40 40 \newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}\xspace} % CC symbolic name 41 41 \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 name43 42 \newcommand{\Celeven}{C11\xspace} % C11 symbolic name 44 43 \newcommand{\Csharp}{C\raisebox{0.4ex}{\#}\xspace} % C# symbolic name -
src/GenPoly/Specialize.cc
r395fc37 r6f95000 77 77 } 78 78 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), or81 /// 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 95 79 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(); 109 82 } 110 83 return false; … … 137 110 } 138 111 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 ) ) { 144 116 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 ) ); 147 119 } 148 120 *out++ = new TupleExpr( exprs ); 149 121 } 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 ); 162 141 } 163 delete expr; 164 } else { 165 // non-tuple type - output a clone of the expression 166 *out++ = expr; 142 delete last; 167 143 } 168 144 } … … 197 173 std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin(); 198 174 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 201 178 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. 203 180 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 213 192 appExpr->set_env( maybeClone( env ) ); 214 193 if ( inferParams ) { -
src/InitTweak/GenInit.cc
r395fc37 r6f95000 218 218 219 219 bool CtorDtor::isManaged( Type * type ) const { 220 // need to clear and reset qualifiers when determining if a type is managed221 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );222 type->get_qualifiers() = Type::Qualifiers();223 220 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 224 221 // tuple is also managed if any of its components are managed -
src/Parser/parser.yy
r395fc37 r6f95000 412 412 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_REALFRACTIONconstant( *$2 ) ) ); } 413 413 | 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 ) ) ); } 417 415 | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector 418 416 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); } 419 | postfix_expression ARROW INTEGERconstant // CFA, tuple index420 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }421 417 | postfix_expression ICR 422 418 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); } -
src/ResolvExpr/Resolver.cc
r395fc37 r6f95000 240 240 functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() ); 241 241 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 currently245 // 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 }254 242 } 255 243 -
src/SymTab/Autogen.cc
r395fc37 r6f95000 151 151 bool hasDynamicLayout( AggrDecl * aggregateDecl ) { 152 152 for ( TypeDecl * param : aggregateDecl->get_parameters() ) { 153 if ( param-> isComplete()) return true;153 if ( param->get_kind() == TypeDecl::Any ) return true; 154 154 } 155 155 return false; -
src/SymTab/Indexer.cc
r395fc37 r6f95000 119 119 FunctionDecl * decl; 120 120 bool isUserDefinedFunc; // properties for this particular decl 121 bool isDefaultCtor; 122 bool isDtor; 121 bool isDefaultFunc; 123 122 bool isCopyFunc; 124 123 }; 125 124 // 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 130 128 std::list< DeclBall > decls; 131 129 … … 134 132 ValueType & operator+=( FunctionDecl * function ) { 135 133 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; 138 135 bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() ); 139 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefault Ctor, isDtor, isCopyFunc } );136 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultFunc, isCopyFunc } ); 140 137 userDefinedFunc = userDefinedFunc || isUserDefinedFunc; 141 userDefinedCtor = userDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) ); 142 userDefinedDtor = userDefinedDtor || (isUserDefinedFunc && isDtor); 138 userDefinedDefaultFunc = userDefinedDefaultFunc || (isUserDefinedFunc && isDefaultFunc); 143 139 userDefinedCopyFunc = userDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); 144 140 return *this; … … 167 163 // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor 168 164 // 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.170 165 for ( std::pair< const std::string, ValueType > & pair : funcMap ) { 171 166 ValueType & val = pair.second; 172 167 for ( ValueType::DeclBall ball : val.decls ) { 173 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefined Ctor && ball.isDefaultCtor) || (! val.userDefinedCopyFunc && ball.isCopyFunc) || (! val.userDefinedDtor && ball.isDtor) ) {168 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedDefaultFunc && ball.isDefaultFunc) || (! val.userDefinedCopyFunc && ball.isCopyFunc) ) { 174 169 // decl conforms to the rules described above, so it should be seen by the requester 175 170 out.push_back( ball.decl ); -
src/SymTab/Validate.cc
r395fc37 r6f95000 224 224 HoistStruct::hoistStruct( translationUnit ); 225 225 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 226 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions227 226 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass 228 227 acceptAll( translationUnit, epc ); 228 acceptAll( translationUnit, lrt ); 229 229 ReturnChecker::checkFunctionReturns( translationUnit ); 230 230 compoundliteral.mutateDeclarationList( translationUnit ); … … 840 840 assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %d", functionDecl->get_name().c_str(), retVals.size() ); 841 841 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 844 844 DeclarationWithType * ret = retVals.front(); 845 845 if ( ret->get_name() == "" ) { -
src/SynTree/TypeDecl.cc
r395fc37 r6f95000 25 25 26 26 std::string TypeDecl::typeString() const { 27 static const std::stringkindNames[] = { "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 ]; 29 29 } 30 30 -
src/tests/.expect/tuplePolymorphism.txt
r395fc37 r6f95000 3 3 123 999.123 456 4 4 246 1998.25 912 5 1.21 x 10.21 1111 v 54385938 1111 v 54385938 -
src/tests/memberCtors.c
r395fc37 r6f95000 30 30 WrappedInt x, y, z; 31 31 }; 32 33 void ?{}(A * a) {34 // currently must define default ctor, since there's no "= default" syntax35 }36 32 37 33 void ?{}(A * a, int x) { -
src/tests/tuplePolymorphism.c
r395fc37 r6f95000 14 14 // 15 15 16 // packed is needed so that structs are not passed with the same alignment as function arguments17 __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 match30 [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 triples35 16 forall(otype T | { T ?+?(T, T); }) 36 17 [T, T, T] ?+?([T, T, T] x, [T, T, T] y) { … … 59 40 [x1, x2, x3] = zzz+zzz; 60 41 printf("%d %g %d\n", x1, x2, x3); 61 62 // ensure non-matching assertions are specialized correctly63 g((A){ 1.21, 'x', 10.21}, (B){ 1111LL, 'v', 54385938LL });64 42 } 65 43
Note:
See TracChangeset
for help on using the changeset viewer.