Changeset 4d2d7e27


Ignore:
Timestamp:
Oct 16, 2023, 3:04:18 PM (14 months ago)
Author:
Peter A. Buhr <pabuhr@…>
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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • doc/proposals/enum.tex

    r54e59dd r4d2d7e27  
    7373
    7474
    75 
    76 %%
    77 %% Submission ID.
    78 %% Use this when submitting an article to a sponsored event. You'll
    79 %% receive a unique submission ID from the organizers
    80 %% 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 bibliography
    85 %% 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 include
    89 %% support for advanced citation of software artefact from the
    90 %% biblatex-software package, also separately available on CTAN.
    91 %%
    92 %% Look at the sample-*-biblatex.tex files for templates showcasing
    93 %% the biblatex styles.
    94 %%
    95 
    96 %%
    97 %% The majority of ACM publications use numbered citations and
    98 %% references.  The command \citestyle{authoryear} switches to the
    99 %% "author year" style.
    100 %%
    101 %% If you are preparing content for an event
    102 %% sponsored by ACM SIGGRAPH, you must use the "author year" style of
    103 %% citations and references.
    104 %% Uncommenting
    105 %% the next command will enable that style.
    106 %%\citestyle{acmauthoryear}
    107 
    10875%%
    10976%% end of the preamble, start of the body of the document source.
     
    12895%% article.
    12996\begin{abstract}
    130     An enumeration, or enum in short, is a type that defines a list of named constant values in C. Cforall 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.
    13198\end{abstract}
    13299
     
    143110
    144111\section{C-Style Enum}
     112\begin{lstlisting}[style=CStyle, label{lst:weekday}]
     113enum Weekday { Monday, Tuesday, Wednesday, Thursday=10, Friday, Saturday, Sunday };
     114\end{lstlisting}
     115Cforall 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}
     126C-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}]
     130enum Color(char *) { Red="R", Green="G", Blue="B"  };
     131\end{lstlisting}
     132A 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}
     135A 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}
     137A type is enumerable if it can map an integer to a value.
    145138\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}
     139forall(T)
     140trait Enumerable {
     141    T value( *class_name* , int );
     142};
     143\end{lstlisting}
     144The parameter class name stands for the name of an enumeration class, Weekday, for example.
     145
     146\subsection{AutoInitializable}
     147\begin{lstlisting}[style=CStyle]
     148forall(T)
     149trait 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]
     160forall(T)
     161trait 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}
     169A 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
    151171\subsection{Enumerable Type}
    152172\begin{lstlisting}[style=CStyle]
     
    160180};
    161181\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
    163186
    164187(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)
     
    224247Names of labels are distinct in an enum declaration. Cforall therefore allows indexing an enum value with its string representation of a label.
    225248
    226 \subsection{Range Functions and Iteration (Placeholder)}
     249\subsection{Iteration and Range}
     250A Cforall enum is iterable and supports range function.
    227251\begin{lstlisting}[caption={Range Functions}, label{lst:range_functions}, style=CStyle]
    228 enum Weekday(
    229     Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
    230 };
     252struct string;
     253enum(string) Weekday(
     254    Monday = "M", Tuesday = "Tu", ...
     255};
     256for ( i; Weekday ) { sout | i; }
     257>> M Tu W Th F Sat Sun
     258for ( Monday ~= Tuesday )
     259>> M Tu
    231260\end{lstlisting}
    232261
     
    249278}
    250279>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     280enum Color.Label;
    251281Companion( string ) Color = {
    252282    .values = [ "Red", "Green", "Blue" ],
     
    255285>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    256286forall( 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}
     287T value( Companion companion, int index ) { return companion.values[ index ]; }
     288T value( Companion, enum Color.Label );
     289char* label( Companion companion, int index ) { return companion.values[ index ]; }
     290char* label( Companion, enum Color.Label );
     291
     292\end{lstlisting}
     293
     294
     295\subsection{Companion Trait}
     296Users 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}
    262305%%
    263306%% If your work has an appendix, this is the place to put it.
  • src/GenPoly/BoxNew.cpp

    r54e59dd r4d2d7e27  
    376376        ast::Expr const * postvisit( ast::AddressExpr const * expr );
    377377        ast::ReturnStmt const * previsit( ast::ReturnStmt const * stmt );
    378         void previsit( ast::PointerType const * type );
    379         void previsit( ast::FunctionType const * type );
    380378
    381379        void beginScope();
     
    386384        // return value.
    387385
    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.
    395387        ast::vector<ast::Expr>::iterator passTypeVars(
    396388                ast::ApplicationExpr * expr,
    397                 ast::Type const * polyRetType,
    398                 ast::FunctionType const * funcType,
    399                 const TypeVarMap & exprTyVars );
     389                ast::FunctionType const * funcType );
    400390        /// Wraps a function application with a new temporary for the
    401391        /// out-parameter return value.
     
    561551
    562552ast::FunctionDecl const * CallAdapter::previsit( ast::FunctionDecl const * decl ) {
     553        // Prevent type declaration information from leaking out.
     554        GuardScope( scopeTypeVars );
     555
    563556        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 );
    567557                return decl;
    568558        }
    569559
    570         GuardScope( scopeTypeVars );
    571560        GuardValue( retval );
    572561
     
    695684
    696685        assert( typeSubs );
    697         ast::Type const * concRetType = replaceWithConcrete( dynRetType, *typeSubs );
    698         // Used to use dynRetType instead of concRetType; this changed so that
    699         // the correct type parameters are passed for return types (it should be
    700         // the concrete type's parameters, not the formal type's).
    701686        ast::vector<ast::Expr>::iterator argIt =
    702                 passTypeVars( mutExpr, concRetType, function, exprTypeVars );
     687                passTypeVars( mutExpr, function );
    703688        addInferredParams( mutExpr, argIt, function, exprTypeVars );
    704689
     
    778763}
    779764
    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 
    790765void CallAdapter::beginScope() {
    791766        adapters.beginScope();
     
    812787}
    813788
    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 pass
    844                 // 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 
    859789ast::vector<ast::Expr>::iterator CallAdapter::passTypeVars(
    860790                ast::ApplicationExpr * expr,
    861                 ast::Type const * polyRetType,
    862                 ast::FunctionType const * function,
    863                 const TypeVarMap & exprTypeVars ) {
     791                ast::FunctionType const * function ) {
    864792        assert( typeSubs );
    865793        ast::vector<ast::Expr>::iterator arg = expr->args.begin();
     
    880808                        new ast::AlignofExpr( expr->location, ast::deepCopy( concrete ) ) );
    881809                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 the
    909         // 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 < argsToPass
    916                         ; ++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 );
    924810        }
    925811        return arg;
     
    15231409}
    15241410
    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 
    15321411ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) {
    15331412        TypeVarMap localTypeVars = { ast::TypeData() };
     
    15841463        mutDecl->assertions.clear();
    15851464
    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 no
    1605                 // 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 
    16141465        // Prepend each argument group. From last group to first. addAdapters
    16151466        // does do the same, it just does it itself and see all other parameters.
    16161467        spliceBegin( mutDecl->params, inferredParams );
    1617         spliceBegin( mutDecl->params, otypeParams );
    16181468        spliceBegin( mutDecl->params, layoutParams );
    16191469        addAdapters( mutDecl, localTypeVars );
     
    17281578        PolyGenericCalculator();
    17291579
    1730         void previsit( ast::ObjectDecl const * decl );
    17311580        void previsit( ast::FunctionDecl const * decl );
    17321581        void previsit( ast::TypedefDecl const * decl );
     
    17351584        ast::StructDecl const * previsit( ast::StructDecl const * decl );
    17361585        ast::UnionDecl const * previsit( ast::UnionDecl const * decl );
    1737         void previsit( ast::PointerType const * type );
    1738         void previsit( ast::FunctionType const * type );
    17391586        ast::DeclStmt const * previsit( ast::DeclStmt const * stmt );
    17401587        ast::Expr const * postvisit( ast::MemberExpr const * expr );
     
    17721619        /// adding the type variables from the provided type.
    17731620        void beginTypeScope( ast::Type const * );
    1774         /// Enters a new scope for known layouts and offsets, and queues exit calls.
    1775         void beginGenericScope();
    17761621
    17771622        /// Set of generic type layouts known in the current scope,
     
    17851630        /// If the argument of an AddressExpr is MemberExpr, it is stored here.
    17861631        ast::MemberExpr const * addrMember = nullptr;
    1787         /// Used to avoid recursing too deep in type declarations.
    1788         bool expect_func_type = false;
    17891632};
    17901633
     
    18081651}
    18091652
    1810 void PolyGenericCalculator::previsit( ast::ObjectDecl const * decl ) {
     1653void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) {
     1654        GuardScope( *this );
    18111655        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         }
    18261656}
    18271657
     
    18841714}
    18851715
    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 probably
    1897         // function parameters they don't help us with the layout and offsets so
    1898         // 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 is
    1902         // 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 ) {
    19131716ast::DeclStmt const * PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) {
    19141717        ast::ObjectDecl const * decl = stmt->decl.as<ast::ObjectDecl>();
     
    24002203}
    24012204
    2402 void PolyGenericCalculator::beginGenericScope() {
    2403         GuardScope( *this );
    2404         // We expect the first function type see to be the type relating to this
    2405         // scope but any further type is probably some unrelated function pointer
    2406         // keep track of whrich is the first.
    2407         GuardValue( expect_func_type ) = true;
    2408 }
    2409 
    24102205// --------------------------------------------------------------------------
    2411 /// No common theme found.
     2206/// Removes unneeded or incorrect type information.
    24122207/// * Replaces initialization of polymorphic values with alloca.
    24132208/// * Replaces declaration of dtype/ftype with appropriate void expression.
Note: See TracChangeset for help on using the changeset viewer.