Changeset 4d2d7e27
- Timestamp:
- Oct 16, 2023, 3:04:18 PM (14 months ago)
- Branches:
- master
- Children:
- 278e162
- Parents:
- 54e59dd (diff), e14d169 (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. - Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/enum.tex
r54e59dd r4d2d7e27 73 73 74 74 75 76 %%77 %% Submission ID.78 %% Use this when submitting an article to a sponsored event. You'll79 %% receive a unique submission ID from the organizers80 %% of the event, and this ID should be used as the parameter to this command.81 %%\acmSubmissionID{123-A56-BU3}82 83 %%84 %% For managing citations, it is recommended to use bibliography85 %% files in BibTeX format.86 %%87 %% You can then either use BibTeX with the ACM-Reference-Format style,88 %% or BibLaTeX with the acmnumeric or acmauthoryear sytles, that include89 %% support for advanced citation of software artefact from the90 %% biblatex-software package, also separately available on CTAN.91 %%92 %% Look at the sample-*-biblatex.tex files for templates showcasing93 %% the biblatex styles.94 %%95 96 %%97 %% The majority of ACM publications use numbered citations and98 %% references. The command \citestyle{authoryear} switches to the99 %% "author year" style.100 %%101 %% If you are preparing content for an event102 %% sponsored by ACM SIGGRAPH, you must use the "author year" style of103 %% citations and references.104 %% Uncommenting105 %% the next command will enable that style.106 %%\citestyle{acmauthoryear}107 108 75 %% 109 76 %% end of the preamble, start of the body of the document source. … … 128 95 %% article. 129 96 \begin{abstract} 130 An enumeration, or enum in short, is a type that defines a list of named constant values in C. C forall extends the enumeration with additional features.97 An enumeration, or enum in short, is a type that defines a list of named constant values in C. C uses integral type as the underlying representation of enum. Cforall extends C enum to allow more types, including custom types, to be used as enumeration inner representation. 131 98 \end{abstract} 132 99 … … 143 110 144 111 \section{C-Style Enum} 112 \begin{lstlisting}[style=CStyle, label{lst:weekday}] 113 enum Weekday { Monday, Tuesday, Wednesday, Thursday=10, Friday, Saturday, Sunday }; 114 \end{lstlisting} 115 Cforall supports the C-Style enumeration (C-enum for short). It has the same syntax as C and resembles the same language semantics. In code~\ref{lst:weekday} example, the syntax defines an enum class $Weekday$ with enumerators $Monday$, $Tuesday$, $Wednesday$, $Thursday$, $Friday$, $Saturday$ and $Sunday$ in order. The successor of $Tuesday$ is $Monday$ and the predecessor of $Tuesday$ is $Wednesday$. Enumerators have an integral type, either being explicitly initialized by an initializer or being assigned a value by the compiler. For example, $Thursday$ has been assigned with value $10$. If not explicitly initialized, the first value of an enum, $Monday$ in the $Weekday$ example, has the integer value 0. Other uninitialized enum value has a value that is equal to their successor $+ 1$. The enum value $Tuesday$, $Wednesday$, $Friday$, $Saturday$, and $Sunday$ have value 1, 2, 11, 12, and 13 respectively. 116 117 \begin{lstlisting}[label{lst:enum_scope}, style=CStyle] 118 { 119 { 120 enum RGB {R, G, B}; 121 int i = R // i == 0 122 } 123 int j = G; // ERROR! G is not declared in this scope 124 } 125 \end{lstlisting} 126 C-enums are unscoped: enumerators declared inside of an enum are visible in the enclosing scope of the enum class. 127 128 \section{Cforall-Style Enum} 129 \begin{lstlisting}[style=CStyle, label{lst:color}] 130 enum Color(char *) { Red="R", Green="G", Blue="B" }; 131 \end{lstlisting} 132 A Cforall enumeration is parameterized by a type declared. Cforall allows any oType in the enum declaration, and values assigned to enumerators must be in the declared type. 133 134 \section{Enumerable Type Traits} 135 A trait is a collection of constraints in Cforall, which can be used to describe types. Cforall standard library defines traits to categorize types that are related enumeration features. 136 \subsection{Enumerable} 137 A type is enumerable if it can map an integer to a value. 145 138 \begin{lstlisting}[style=CStyle] 146 enum Weekday { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; 147 \end{lstlisting} 148 Cforall supports the classic C-Style enumeration (C-enum for short) and its syntax is consistent with C. No internal data structure is generated for C-enum, and C-enum does not provide the Cforall-enum interface methods. 149 150 \section{Cforall Enum} 139 forall(T) 140 trait Enumerable { 141 T value( *class_name* , int ); 142 }; 143 \end{lstlisting} 144 The parameter class name stands for the name of an enumeration class, Weekday, for example. 145 146 \subsection{AutoInitializable} 147 \begin{lstlisting}[style=CStyle] 148 forall(T) 149 trait AutoInitializable { 150 void ?()( T & t, zero_t ); 151 void ?()( T & t, one_t ); 152 S& ?+=?( T & t, one_t ); 153 void ?{}( T &, T ); 154 T ?{}( T &, T ); 155 }; 156 \end{lstlisting} 157 158 \subsection{AutoInitializable} 159 \begin{lstlisting}[style=CStyle] 160 forall(T) 161 trait AutoInitializable { 162 void ?()( T & t, zero_t ); 163 void ?()( T & t, one_t ); 164 S& ?+=?( T & t, one_t ); 165 void ?{}( T &, T ); 166 T ?{}( T &, T ); 167 }; 168 \end{lstlisting} 169 A type is AutoInitializable if it has defined a zero\_t constructor, a one\_t constructor, an addition assignment operator, a copy constructor, and a copy assignment operator. 170 151 171 \subsection{Enumerable Type} 152 172 \begin{lstlisting}[style=CStyle] … … 160 180 }; 161 181 \end{lstlisting} 162 A type is enumerable in Cforall if it has defined 0, 1, increment operator, copy constructor, and copy assignment operator. 182 183 184 185 163 186 164 187 (Should change the definition of enumerable to something else. Maybe auto-constructible. If a type is not auto-constructible, all enumeration must be explicitly initialized) … … 224 247 Names of labels are distinct in an enum declaration. Cforall therefore allows indexing an enum value with its string representation of a label. 225 248 226 \subsection{Range Functions and Iteration (Placeholder)} 249 \subsection{Iteration and Range} 250 A Cforall enum is iterable and supports range function. 227 251 \begin{lstlisting}[caption={Range Functions}, label{lst:range_functions}, style=CStyle] 228 enum Weekday( 229 Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday 230 }; 252 struct string; 253 enum(string) Weekday( 254 Monday = "M", Tuesday = "Tu", ... 255 }; 256 for ( i; Weekday ) { sout | i; } 257 >> M Tu W Th F Sat Sun 258 for ( Monday ~= Tuesday ) 259 >> M Tu 231 260 \end{lstlisting} 232 261 … … 249 278 } 250 279 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 280 enum Color.Label; 251 281 Companion( string ) Color = { 252 282 .values = [ "Red", "Green", "Blue" ], … … 255 285 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 256 286 forall( T | enumerable(T) ) 257 T* value( Companion, int ); 258 char* label( Companion, int ); 259 \end{lstlisting} 260 261 \subsection{TODO - Type trait for Cforall - Enum} 287 T value( Companion companion, int index ) { return companion.values[ index ]; } 288 T value( Companion, enum Color.Label ); 289 char* label( Companion companion, int index ) { return companion.values[ index ]; } 290 char* label( Companion, enum Color.Label ); 291 292 \end{lstlisting} 293 294 295 \subsection{Companion Trait} 296 Users can define the companion object themselves. A companion object should define an array of any type called values and an array of strings representing a label. Defining a companion object effectively creates a new enumerable type. 297 298 \subsection{Companion Mapping} 299 300 301 302 \begin{lstlisting}[caption={Enum Type Functions}, label{lst:cforall_enum_functions}, style=CStyle] 303 304 \end{lstlisting} 262 305 %% 263 306 %% If your work has an appendix, this is the place to put it. -
src/GenPoly/BoxNew.cpp
r54e59dd r4d2d7e27 376 376 ast::Expr const * postvisit( ast::AddressExpr const * expr ); 377 377 ast::ReturnStmt const * previsit( ast::ReturnStmt const * stmt ); 378 void previsit( ast::PointerType const * type );379 void previsit( ast::FunctionType const * type );380 378 381 379 void beginScope(); … … 386 384 // return value. 387 385 388 /// Pass the extra type parameters from polymorphic generic arguments or 389 /// return types into a function application. 390 ast::vector<ast::Expr>::iterator passArgTypeVars( 391 ast::ApplicationExpr * expr, ast::Type const * parmType, 392 ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg, 393 const TypeVarMap & exprTyVars, std::set<std::string> & seenTypes ); 394 /// Passes extra type parameters into a polymorphic function application. 386 /// Passes extra layout arguments for sized polymorphic type parameters. 395 387 ast::vector<ast::Expr>::iterator passTypeVars( 396 388 ast::ApplicationExpr * expr, 397 ast::Type const * polyRetType, 398 ast::FunctionType const * funcType, 399 const TypeVarMap & exprTyVars ); 389 ast::FunctionType const * funcType ); 400 390 /// Wraps a function application with a new temporary for the 401 391 /// out-parameter return value. … … 561 551 562 552 ast::FunctionDecl const * CallAdapter::previsit( ast::FunctionDecl const * decl ) { 553 // Prevent type declaration information from leaking out. 554 GuardScope( scopeTypeVars ); 555 563 556 if ( nullptr == decl->stmts ) { 564 // This may keep TypeDecls we don't ever want from sneaking in.565 // Not visiting child nodes might just be faster.566 GuardScope( scopeTypeVars );567 557 return decl; 568 558 } 569 559 570 GuardScope( scopeTypeVars );571 560 GuardValue( retval ); 572 561 … … 695 684 696 685 assert( typeSubs ); 697 ast::Type const * concRetType = replaceWithConcrete( dynRetType, *typeSubs );698 // Used to use dynRetType instead of concRetType; this changed so that699 // the correct type parameters are passed for return types (it should be700 // the concrete type's parameters, not the formal type's).701 686 ast::vector<ast::Expr>::iterator argIt = 702 passTypeVars( mutExpr, concRetType, function, exprTypeVars);687 passTypeVars( mutExpr, function ); 703 688 addInferredParams( mutExpr, argIt, function, exprTypeVars ); 704 689 … … 778 763 } 779 764 780 void CallAdapter::previsit( ast::PointerType const * type ) {781 GuardScope( scopeTypeVars );782 makeTypeVarMap( type, scopeTypeVars );783 }784 785 void CallAdapter::previsit( ast::FunctionType const * type ) {786 GuardScope( scopeTypeVars );787 makeTypeVarMap( type, scopeTypeVars );788 }789 790 765 void CallAdapter::beginScope() { 791 766 adapters.beginScope(); … … 812 787 } 813 788 814 // arg is an in/out parameter that matches the return value.815 ast::vector<ast::Expr>::iterator CallAdapter::passArgTypeVars(816 ast::ApplicationExpr * expr, ast::Type const * paramType,817 ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg,818 const TypeVarMap & exprTypeVars, std::set<std::string> & seenTypes ) {819 ast::Type const * polyType = isPolyType( paramType, exprTypeVars );820 if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {821 return arg;822 }823 824 std::string typeName = Mangle::mangleType( polyType );825 if ( seenTypes.count( typeName ) ) return arg;826 827 arg = expr->args.insert( arg,828 new ast::SizeofExpr( expr->location, ast::deepCopy( argBaseType ) )829 );830 arg++;831 arg = expr->args.insert( arg,832 new ast::AlignofExpr( expr->location, ast::deepCopy( argBaseType ) )833 );834 arg++;835 if ( dynamic_cast<ast::StructInstType const *>( polyType ) ) {836 auto argBaseStructType =837 dynamic_cast<ast::StructInstType const *>( argBaseType );838 if ( nullptr == argBaseStructType ) {839 SemanticError( expr,840 "Cannot pass non-structure type for generic struct: " );841 }842 843 // Zero-length arrays are forbidden by C, so don't pass844 // offset for empty structure.845 if ( !argBaseStructType->base->members.empty() ) {846 arg = expr->args.insert( arg,847 new ast::OffsetPackExpr(848 expr->location,849 ast::deepCopy( argBaseStructType ) )850 );851 arg++;852 }853 }854 855 seenTypes.insert( typeName );856 return arg;857 }858 859 789 ast::vector<ast::Expr>::iterator CallAdapter::passTypeVars( 860 790 ast::ApplicationExpr * expr, 861 ast::Type const * polyRetType, 862 ast::FunctionType const * function, 863 const TypeVarMap & exprTypeVars ) { 791 ast::FunctionType const * function ) { 864 792 assert( typeSubs ); 865 793 ast::vector<ast::Expr>::iterator arg = expr->args.begin(); … … 880 808 new ast::AlignofExpr( expr->location, ast::deepCopy( concrete ) ) ); 881 809 arg++; 882 }883 884 // Add size/align for generic types to parameter list.885 if ( !expr->func->result ) return arg;886 ast::FunctionType const * funcType = getFunctionType( expr->func->result );887 assert( funcType );888 889 // This iterator points at first original argument.890 ast::vector<ast::Expr>::const_iterator funcArg;891 // Names for generic types we've seen.892 std::set<std::string> seenTypes;893 894 // A polymorphic return type may need to be added to the argument list.895 if ( polyRetType ) {896 assert( typeSubs );897 auto concRetType = replaceWithConcrete( polyRetType, *typeSubs );898 // TODO: This write-back may not be correct.899 arg = passArgTypeVars( expr, polyRetType, concRetType,900 arg, exprTypeVars, seenTypes );901 // Skip the return parameter in the argument list.902 funcArg = arg + 1;903 } else {904 funcArg = arg;905 }906 907 // TODO:908 // I believe this is (starts as) the number of original arguments to the909 // function with the args before funcArg all being inserted.910 ptrdiff_t argsToPass = std::distance( funcArg, expr->args.cend() );911 912 // Add type information args for presently unseen types in parameter list.913 ast::vector<ast::Type>::const_iterator funcParam = funcType->params.begin();914 // assert( funcType->params.size() == argsToPass );915 for ( ; funcParam != funcType->params.end() && 0 < argsToPass916 ; ++funcParam, --argsToPass ) {917 assert( 0 < argsToPass );918 assert( argsToPass <= (ptrdiff_t)expr->args.size() );919 ptrdiff_t index = expr->args.size() - argsToPass;920 ast::Type const * argType = expr->args[index]->result;921 if ( nullptr == argType ) continue;922 arg = passArgTypeVars( expr, *funcParam, argType,923 arg, exprTypeVars, seenTypes );924 810 } 925 811 return arg; … … 1523 1409 } 1524 1410 1525 ast::ObjectDecl * makePtr(1526 CodeLocation const & location, std::string const & name ) {1527 return new ast::ObjectDecl( location, name,1528 new ast::PointerType( makeSizeAlignType() ),1529 nullptr, ast::Storage::Classes(), ast::Linkage::C, nullptr );1530 }1531 1532 1411 ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) { 1533 1412 TypeVarMap localTypeVars = { ast::TypeData() }; … … 1584 1463 mutDecl->assertions.clear(); 1585 1464 1586 // Add size/align for generic parameter types to parameter list.1587 std::set<std::string> seenTypes;1588 ast::vector<ast::DeclWithType> otypeParams;1589 for ( ast::ptr<ast::DeclWithType> & funcParam : mutDecl->params ) {1590 ast::Type const * polyType = isPolyType( funcParam->get_type(), localTypeVars );1591 if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1592 continue;1593 }1594 std::string typeName = Mangle::mangleType( polyType );1595 if ( seenTypes.count( typeName ) ) continue;1596 seenTypes.insert( typeName );1597 1598 auto sizeParam = makeObj( funcParam->location, sizeofName( typeName ) );1599 otypeParams.emplace_back( sizeParam );1600 1601 auto alignParam = makeObj( funcParam->location, alignofName( typeName ) );1602 otypeParams.emplace_back( alignParam );1603 1604 // Zero-length arrays are illegal in C, so empty structs have no1605 // offset array.1606 if ( auto * polyStruct =1607 dynamic_cast<ast::StructInstType const *>( polyType ) ;1608 polyStruct && !polyStruct->base->members.empty() ) {1609 auto offsetParam = makePtr( funcParam->location, offsetofName( typeName ) );1610 otypeParams.emplace_back( offsetParam );1611 }1612 }1613 1614 1465 // Prepend each argument group. From last group to first. addAdapters 1615 1466 // does do the same, it just does it itself and see all other parameters. 1616 1467 spliceBegin( mutDecl->params, inferredParams ); 1617 spliceBegin( mutDecl->params, otypeParams );1618 1468 spliceBegin( mutDecl->params, layoutParams ); 1619 1469 addAdapters( mutDecl, localTypeVars ); … … 1728 1578 PolyGenericCalculator(); 1729 1579 1730 void previsit( ast::ObjectDecl const * decl );1731 1580 void previsit( ast::FunctionDecl const * decl ); 1732 1581 void previsit( ast::TypedefDecl const * decl ); … … 1735 1584 ast::StructDecl const * previsit( ast::StructDecl const * decl ); 1736 1585 ast::UnionDecl const * previsit( ast::UnionDecl const * decl ); 1737 void previsit( ast::PointerType const * type );1738 void previsit( ast::FunctionType const * type );1739 1586 ast::DeclStmt const * previsit( ast::DeclStmt const * stmt ); 1740 1587 ast::Expr const * postvisit( ast::MemberExpr const * expr ); … … 1772 1619 /// adding the type variables from the provided type. 1773 1620 void beginTypeScope( ast::Type const * ); 1774 /// Enters a new scope for known layouts and offsets, and queues exit calls.1775 void beginGenericScope();1776 1621 1777 1622 /// Set of generic type layouts known in the current scope, … … 1785 1630 /// If the argument of an AddressExpr is MemberExpr, it is stored here. 1786 1631 ast::MemberExpr const * addrMember = nullptr; 1787 /// Used to avoid recursing too deep in type declarations.1788 bool expect_func_type = false;1789 1632 }; 1790 1633 … … 1808 1651 } 1809 1652 1810 void PolyGenericCalculator::previsit( ast::ObjectDecl const * decl ) { 1653 void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) { 1654 GuardScope( *this ); 1811 1655 beginTypeScope( decl->type ); 1812 }1813 1814 void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) {1815 beginGenericScope();1816 beginTypeScope( decl->type );1817 1818 // TODO: Going though dec->params does not work for some reason.1819 for ( ast::ptr<ast::Type> const & funcParam : decl->type->params ) {1820 // Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`1821 ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );1822 if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1823 knownLayouts.insert( Mangle::mangleType( polyType ) );1824 }1825 }1826 1656 } 1827 1657 … … 1884 1714 } 1885 1715 1886 void PolyGenericCalculator::previsit( ast::PointerType const * type ) {1887 beginTypeScope( type );1888 }1889 1890 void PolyGenericCalculator::previsit( ast::FunctionType const * type ) {1891 beginTypeScope( type );1892 1893 GuardValue( expect_func_type );1894 GuardScope( *this );1895 1896 // The other functions type we will see in this scope are probably1897 // function parameters they don't help us with the layout and offsets so1898 // don't mark them as known in this scope.1899 expect_func_type = false;1900 1901 // Make sure that any type information passed into the function is1902 // accounted for.1903 for ( ast::ptr<ast::Type> const & funcParam : type->params ) {1904 // Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`1905 ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );1906 if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1907 knownLayouts.insert( Mangle::mangleType( polyType ) );1908 }1909 }1910 }1911 1912 //void PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) {1913 1716 ast::DeclStmt const * PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) { 1914 1717 ast::ObjectDecl const * decl = stmt->decl.as<ast::ObjectDecl>(); … … 2400 2203 } 2401 2204 2402 void PolyGenericCalculator::beginGenericScope() {2403 GuardScope( *this );2404 // We expect the first function type see to be the type relating to this2405 // scope but any further type is probably some unrelated function pointer2406 // keep track of whrich is the first.2407 GuardValue( expect_func_type ) = true;2408 }2409 2410 2205 // -------------------------------------------------------------------------- 2411 /// No common theme found.2206 /// Removes unneeded or incorrect type information. 2412 2207 /// * Replaces initialization of polymorphic values with alloca. 2413 2208 /// * Replaces declaration of dtype/ftype with appropriate void expression.
Note: See TracChangeset
for help on using the changeset viewer.