Changeset b63e376 for doc/refrat/refrat.tex
 Timestamp:
 Mar 8, 2016, 10:24:43 PM (8 years ago)
 Branches:
 ADT, aaronthesis, armeh, astexperimental, cleanupdtors, ctor, deferred_resn, demangler, enum, forallpointerdecay, gc_noraii, jacob/cs343translation, jenkinssandbox, master, memory, newast, newastuniqueexpr, newenv, no_list, persistentindexer, pthreademulation, qualifiedEnum, resolvnew, string, with_gc
 Children:
 ae357ec
 Parents:
 4040425
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

doc/refrat/refrat.tex
r4040425 rb63e376 62 62 \renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}{2.0ex \@plus 1ex \@minus .2ex}{1em}{\normalfont\normalsize\bfseries}} 63 63 64 % index macros 64 65 \newcommand{\italic}[1]{\emph{\hyperpage{#1}}} 65 66 \newcommand{\definition}[1]{\textbf{\hyperpage{#1}}} … … 133 134 % adjust listings macros 134 135 \lstdefinelanguage{CFA}[ANSI]{C}% 135 {morekeywords={asm,_Alignas,_Alignof,_At,_Atomic,_Bool,catch,catchResume,choose,_Complex, context,disable,dtype,enable,136 fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,lvalue,_Noreturn, restrict,_Static_assert,137 _Thread_local,throw,throwResume,try, type,},136 {morekeywords={asm,_Alignas,_Alignof,_At,_Atomic,_Bool,catch,catchResume,choose,_Complex,trait,disable,dtype,enable, 137 fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,lvalue,_Noreturn,otype,restrict,_Static_assert, 138 _Thread_local,throw,throwResume,try,}, 138 139 }% 139 140 … … 280 281 An instantiation of the generic type is written by specifying the type parameters in parentheses after the name of the generic type generator: 281 282 \begin{lstlisting} 282 forall( type T  sumable( T ) ) struct pair {283 forall( otype T  sumable( T ) ) struct pair { 283 284 T x; 284 285 T y; … … 292 293 Polymorphic functions may have generic types as parameters, and those generic types may use type parameters of the polymorphic function as type parameters of the generic type: 293 294 \begin{lstlisting} 294 forall( type T ) void swap( pair(T) *p ) {295 forall( otype T ) void swap( pair(T) *p ) { 295 296 T z = p>x; 296 297 p>x = p>y; … … 302 303 \subsubsection{Constraints} 303 304 304 To avoid unduly constraining implementors, the generic type generator definition must be visible at any point where it is instantiated. Forward declarations of generic type generators are not forbidden, but the definition must be visible to instantiate the generic type. Equivalently, instantiations of generic types are not allowed to be incomplete types. 305 To avoid unduly constraining implementors, the generic type generator definition must be visible at any point where it is instantiated. 306 Forward declarations of generic type generators are not forbidden, but the definition must be visible to instantiate the generic type. Equivalently, instantiations of generic types are not allowed to be incomplete types. 305 307 306 308 \examples 307 309 \begin{lstlisting} 308 forall( type T ) struct A;309 310 forall( type T ) struct B {310 forall( otype T ) struct A; 311 312 forall( otype T ) struct B { 311 313 A(T) *a; // legal, but cannot instantiate B(T) 312 314 }; … … 314 316 B(T) x; // illegal, *x.a is of an incomplete generic type 315 317 316 forall( type T ) struct A {318 forall( otype T ) struct A { 317 319 B( T ) *b; 318 320 }; … … 321 323 322 324 // box.h: 323 forall( type T ) struct box;324 forall( type T ) box( T ) *make_box( T );325 forall( type T ) void use_box( box( T ) *b );325 forall( otype T ) struct box; 326 forall( otype T ) box( T ) *make_box( T ); 327 forall( otype T ) void use_box( box( T ) *b ); 326 328 327 329 // main.c: … … 410 412 411 413 \subsubsection{Specialization} 412 A function or value whose type is polymorphic may be implicitly converted to one whose type is 413 \Index{less polymorphic} by binding values to one or more of its \Index{inferred parameter}. 414 A function or value whose type is polymorphic may be implicitly converted to one whose type is \Index{less polymorphic} by binding values to one or more of its \Index{inferred parameter}. 414 415 Any value that is legal for the inferred parameter may be used, including other inferred parameters. 415 416 416 If, after the inferred parameter binding, an \Index{assertion parameter} has no inferred parameters in its type, then an object or function must be visible at the point of the specialization that has the same identifier as the assertion parameter and has a type that is compatible\index{compatible 417 type} with or can be specialized to the type of the assertion parameter.The assertion parameter is bound to that object or function.417 If, after the inferred parameter binding, an \Index{assertion parameter} has no inferred parameters in its type, then an object or function must be visible at the point of the specialization that has the same identifier as the assertion parameter and has a type that is compatible\index{compatible type} with or can be specialized to the type of the assertion parameter. 418 The assertion parameter is bound to that object or function. 418 419 419 420 The type of the specialization is the type of the original with the bound inferred parameters and the bound assertion parameters replaced by their bound values. … … 422 423 The type 423 424 \begin{lstlisting} 424 forall( type T,type U ) void (*)( T, U );425 forall( otype T, otype U ) void (*)( T, U ); 425 426 \end{lstlisting} 426 427 can be specialized to (among other things) 427 428 \begin{lstlisting} 428 forall( type T ) void (*)( T, T ); // U bound to T429 forall( type T ) void (*)( T, real ); // U bound to real430 forall( type U ) void (*)( real, U ); // T bound to real429 forall( otype T ) void (*)( T, T ); // U bound to T 430 forall( otype T ) void (*)( T, real ); // U bound to real 431 forall( otype U ) void (*)( real, U ); // T bound to real 431 432 void f( real, real ); // both bound to real 432 433 \end{lstlisting} … … 434 435 The type 435 436 \begin{lstlisting} 436 forall( type T  T ?+?( T, T ) ) T (*)( T );437 forall( otype T  T ?+?( T, T ) ) T (*)( T ); 437 438 \end{lstlisting} 438 439 can be specialized to (among other things) … … 494 495 If \lstinline$int$ can represent all the values of \lstinline$unsigned short$, then the cost of an implicit conversion from \lstinline$unsigned short$ to \lstinline$unsigned$ is 2: 495 496 \lstinline$unsigned short$ to \lstinline$int$ to \lstinline$unsigned$. 496 Otherwise, 497 \lstinline$unsigned short$ is converted directly to \lstinline$unsigned$, and the cost is 1. 497 Otherwise, \lstinline$unsigned short$ is converted directly to \lstinline$unsigned$, and the cost is 1. 498 498 499 499 \item … … 508 508 \rhs \lstinline$forall$ 509 509 \rhs \lstinline$lvalue$ 510 \rhs \lstinline$ context$510 \rhs \lstinline$trait$ 511 511 \rhs \lstinline$dtype$ 512 512 \rhs \lstinline$ftype$ … … 539 539 A \nonterm{constantexpression} that evaluates to 0 is effectively compatible with every pointer type. 540 540 541 In C, the integer constants 0 and 1 suffice because the integer promotion rules can convert them to any arithmetic type, and the rules for pointer expressions treat constant expressions evaluating to 542 0 as a special case. 541 In C, the integer constants 0 and 1 suffice because the integer promotion rules can convert them to any arithmetic type, and the rules for pointer expressions treat constant expressions evaluating to 0 as a special case. 543 542 However, userdefined arithmetic types often need the equivalent of a 1 or 0 for their functions or operators, polymorphic functions often need 0 and 1 constants of a type matching their polymorphic parameters, and userdefined pointerlike types may need a null value. 544 543 Defining special constants for a userdefined type is more efficient than defining a conversion to the type from \lstinline$_Bool$. … … 836 835 \predefined 837 836 \begin{lstlisting} 838 forall( type T ) lvalue T ?[?]( T *, ptrdiff_t );@\use{ptrdiff_t}@839 forall( type T ) lvalue _Atomic T ?[?]( _Atomic T *, ptrdiff_t );840 forall( type T ) lvalue const T ?[?]( const T *, ptrdiff_t );841 forall( type T ) lvalue restrict T ?[?]( restrict T *, ptrdiff_t );842 forall( type T ) lvalue volatile T ?[?]( volatile T *, ptrdiff_t );843 forall( type T ) lvalue _Atomic const T ?[?]( _Atomic const T *, ptrdiff_t );844 forall( type T ) lvalue _Atomic restrict T ?[?]( _Atomic restrict T *, ptrdiff_t );845 forall( type T ) lvalue _Atomic volatile T ?[?]( _Atomic volatile T *, ptrdiff_t );846 forall( type T ) lvalue const restrict T ?[?]( const restrict T *, ptrdiff_t );847 forall( type T ) lvalue const volatile T ?[?]( const volatile T *, ptrdiff_t );848 forall( type T ) lvalue restrict volatile T ?[?]( restrict volatile T *, ptrdiff_t );849 forall( type T ) lvalue _Atomic const restrict T ?[?]( _Atomic const restrict T *, ptrdiff_t );850 forall( type T ) lvalue _Atomic const volatile T ?[?]( _Atomic const volatile T *, ptrdiff_t );851 forall( type T ) lvalue _Atomic restrict volatile T ?[?]( _Atomic restrict volatile T *, ptrdiff_t );852 forall( type T ) lvalue const restrict volatile T ?[?]( const restrict volatile T *, ptrdiff_t );853 forall( type T ) lvalue _Atomic const restrict volatile T ?[?]( _Atomic const restrict volatile T *, ptrdiff_t );837 forall( otype T ) lvalue T ?[?]( T *, ptrdiff_t );@\use{ptrdiff_t}@ 838 forall( otype T ) lvalue _Atomic T ?[?]( _Atomic T *, ptrdiff_t ); 839 forall( otype T ) lvalue const T ?[?]( const T *, ptrdiff_t ); 840 forall( otype T ) lvalue restrict T ?[?]( restrict T *, ptrdiff_t ); 841 forall( otype T ) lvalue volatile T ?[?]( volatile T *, ptrdiff_t ); 842 forall( otype T ) lvalue _Atomic const T ?[?]( _Atomic const T *, ptrdiff_t ); 843 forall( otype T ) lvalue _Atomic restrict T ?[?]( _Atomic restrict T *, ptrdiff_t ); 844 forall( otype T ) lvalue _Atomic volatile T ?[?]( _Atomic volatile T *, ptrdiff_t ); 845 forall( otype T ) lvalue const restrict T ?[?]( const restrict T *, ptrdiff_t ); 846 forall( otype T ) lvalue const volatile T ?[?]( const volatile T *, ptrdiff_t ); 847 forall( otype T ) lvalue restrict volatile T ?[?]( restrict volatile T *, ptrdiff_t ); 848 forall( otype T ) lvalue _Atomic const restrict T ?[?]( _Atomic const restrict T *, ptrdiff_t ); 849 forall( otype T ) lvalue _Atomic const volatile T ?[?]( _Atomic const volatile T *, ptrdiff_t ); 850 forall( otype T ) lvalue _Atomic restrict volatile T ?[?]( _Atomic restrict volatile T *, ptrdiff_t ); 851 forall( otype T ) lvalue const restrict volatile T ?[?]( const restrict volatile T *, ptrdiff_t ); 852 forall( otype T ) lvalue _Atomic const restrict volatile T ?[?]( _Atomic const restrict volatile T *, ptrdiff_t ); 854 853 \end{lstlisting} 855 854 \semantics … … 914 913 \begin{rationale} 915 914 One desirable property of a polymorphic programming language is \define{generalizability}: the ability to replace an abstraction with a more general but equivalent abstraction without requiring changes in any of the uses of the original\cite{Cormack90}. 916 For instance, it should be possible to replace a function ``\lstinline$int f( int );$'' with ``\lstinline$forall( type T ) T f( T );$'' without affecting any calls of \lstinline$f$.915 For instance, it should be possible to replace a function ``\lstinline$int f( int );$'' with ``\lstinline$forall( otype T ) T f( T );$'' without affecting any calls of \lstinline$f$. 917 916 918 917 \CFA\index{deficiencies!generalizability} does not fully possess this property, because … … 928 927 f = g( d, f ); // (3) (unsafe conversion to float) 929 928 \end{lstlisting} 930 If \lstinline$g$ was replaced by ``\lstinline$forall( type T ) T g( T, T );$'', the first and second calls would be unaffected, but the third would change: \lstinline$f$ would be converted to929 If \lstinline$g$ was replaced by ``\lstinline$forall( otype T ) T g( T, T );$'', the first and second calls would be unaffected, but the third would change: \lstinline$f$ would be converted to 931 930 \lstinline$double$, and the result would be a \lstinline$double$. 932 931 933 932 Another example is the function ``\lstinline$void h( int *);$''. 934 933 This function can be passed a 935 \lstinline$void *$ argument, but the generalization ``\lstinline$forall( type T ) void h( T *);$'' can not.934 \lstinline$void *$ argument, but the generalization ``\lstinline$forall( otype T ) void h( T *);$'' can not. 936 935 In this case, \lstinline$void$ is not a valid value for \lstinline$T$ because it is not an object type. 937 936 If unsafe conversions were allowed, \lstinline$T$ could be inferred to be \emph{any} object type, which is undesirable. … … 941 940 A function called ``\lstinline$?()$'' might be part of a numerical differentiation package. 942 941 \begin{lstlisting} 943 extern type Derivative;942 extern otype Derivative; 944 943 extern double ?()( Derivative, double ); 945 944 extern Derivative derivative_of( double (*f)( double ) ); … … 962 961 963 962 \begin{lstlisting} 964 forall( type T ) T h( T );963 forall( otype T ) T h( T ); 965 964 double d = h( 1.5 ); 966 965 \end{lstlisting} … … 969 968 970 969 \begin{lstlisting} 971 forall( type T,type U ) void g( T, U ); // (4)972 forall( type T ) void g( T, T ); // (5)973 forall( type T ) void g( T, long ); // (6)970 forall( otype T, otype U ) void g( T, U ); // (4) 971 forall( otype T ) void g( T, T ); // (5) 972 forall( otype T ) void g( T, long ); // (6) 974 973 void g( long, long ); // (7) 975 974 double d; … … 991 990 The fourth call has no interpretation for (5), because its arguments must have compatible type. (4) is chosen because it does not involve unsafe conversions. 992 991 \begin{lstlisting} 993 forall( type T ) T min( T, T );992 forall( otype T ) T min( T, T ); 994 993 double max( double, double ); 995 context min_max( T ) {@\impl{min_max}@994 trait min_max( T ) {@\impl{min_max}@ 996 995 T min( T, T ); 997 996 T max( T, T ); 998 997 } 999 forall( type U  min_max( U ) ) void shuffle( U, U );998 forall( otype U  min_max( U ) ) void shuffle( U, U ); 1000 999 shuffle( 9, 10 ); 1001 1000 \end{lstlisting} … … 1047 1046 long double ?++( volatile long double * ), ?++( _Atomic volatile long double * ); 1048 1047 1049 forall( type T ) T * ?++( T * restrict volatile * ), * ?++( T * _Atomic restrict volatile * );1050 forall( type T ) _Atomic T * ?++( _Atomic T * restrict volatile * ), * ?++( _Atomic T * _Atomic restrict volatile * );1051 forall( type T ) const T * ?++( const T * restrict volatile * ), * ?++( const T * _Atomic restrict volatile * );1052 forall( type T ) volatile T * ?++( volatile T * restrict volatile * ), * ?++( volatile T * _Atomic restrict volatile * );1053 forall( type T ) restrict T * ?++( restrict T * restrict volatile * ), * ?++( restrict T * _Atomic restrict volatile * );1054 forall( type T ) _Atomic const T * ?++( _Atomic const T * restrict volatile * ),1048 forall( otype T ) T * ?++( T * restrict volatile * ), * ?++( T * _Atomic restrict volatile * ); 1049 forall( otype T ) _Atomic T * ?++( _Atomic T * restrict volatile * ), * ?++( _Atomic T * _Atomic restrict volatile * ); 1050 forall( otype T ) const T * ?++( const T * restrict volatile * ), * ?++( const T * _Atomic restrict volatile * ); 1051 forall( otype T ) volatile T * ?++( volatile T * restrict volatile * ), * ?++( volatile T * _Atomic restrict volatile * ); 1052 forall( otype T ) restrict T * ?++( restrict T * restrict volatile * ), * ?++( restrict T * _Atomic restrict volatile * ); 1053 forall( otype T ) _Atomic const T * ?++( _Atomic const T * restrict volatile * ), 1055 1054 * ?++( _Atomic const T * _Atomic restrict volatile * ); 1056 forall( type T ) _Atomic restrict T * ?++( _Atomic restrict T * restrict volatile * ),1055 forall( otype T ) _Atomic restrict T * ?++( _Atomic restrict T * restrict volatile * ), 1057 1056 * ?++( _Atomic restrict T * _Atomic restrict volatile * ); 1058 forall( type T ) _Atomic volatile T * ?++( _Atomic volatile T * restrict volatile * ),1057 forall( otype T ) _Atomic volatile T * ?++( _Atomic volatile T * restrict volatile * ), 1059 1058 * ?++( _Atomic volatile T * _Atomic restrict volatile * ); 1060 forall( type T ) const restrict T * ?++( const restrict T * restrict volatile * ),1059 forall( otype T ) const restrict T * ?++( const restrict T * restrict volatile * ), 1061 1060 * ?++( const restrict T * _Atomic restrict volatile * ); 1062 forall( type T ) const volatile T * ?++( const volatile T * restrict volatile * ),1061 forall( otype T ) const volatile T * ?++( const volatile T * restrict volatile * ), 1063 1062 * ?++( const volatile T * _Atomic restrict volatile * ); 1064 forall( type T ) restrict volatile T * ?++( restrict volatile T * restrict volatile * ),1063 forall( otype T ) restrict volatile T * ?++( restrict volatile T * restrict volatile * ), 1065 1064 * ?++( restrict volatile T * _Atomic restrict volatile * ); 1066 forall( type T ) _Atomic const restrict T * ?++( _Atomic const restrict T * restrict volatile * ),1065 forall( otype T ) _Atomic const restrict T * ?++( _Atomic const restrict T * restrict volatile * ), 1067 1066 * ?++( _Atomic const restrict T * _Atomic restrict volatile * ); 1068 forall( type T ) _Atomic const volatile T * ?++( _Atomic const volatile T * restrict volatile * ),1067 forall( otype T ) _Atomic const volatile T * ?++( _Atomic const volatile T * restrict volatile * ), 1069 1068 * ?++( _Atomic const volatile T * _Atomic restrict volatile * ); 1070 forall( type T ) _Atomic restrict volatile T * ?++( _Atomic restrict volatile T * restrict volatile * ),1069 forall( otype T ) _Atomic restrict volatile T * ?++( _Atomic restrict volatile T * restrict volatile * ), 1071 1070 * ?++( _Atomic restrict volatile T * _Atomic restrict volatile * ); 1072 forall( type T ) const restrict volatile T * ?++( const restrict volatile T * restrict volatile * ),1071 forall( otype T ) const restrict volatile T * ?++( const restrict volatile T * restrict volatile * ), 1073 1072 * ?++( const restrict volatile T * _Atomic restrict volatile * ); 1074 forall( type T ) _Atomic const restrict volatile T * ?++( _Atomic const restrict volatile T * restrict volatile * ),1073 forall( otype T ) _Atomic const restrict volatile T * ?++( _Atomic const restrict volatile T * restrict volatile * ), 1075 1074 * ?++( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1076 1075 … … 1091 1090 long double ?( volatile long double * ), ?( _Atomic volatile long double * ); 1092 1091 1093 forall( type T ) T * ?( T * restrict volatile * ), * ?( T * _Atomic restrict volatile * );1094 forall( type T ) _Atomic T * ?( _Atomic T * restrict volatile * ), * ?( _Atomic T * _Atomic restrict volatile * );1095 forall( type T ) const T * ?( const T * restrict volatile * ), * ?( const T * _Atomic restrict volatile * );1096 forall( type T ) volatile T * ?( volatile T * restrict volatile * ), * ?( volatile T * _Atomic restrict volatile * );1097 forall( type T ) restrict T * ?( restrict T * restrict volatile * ), * ?( restrict T * _Atomic restrict volatile * );1098 forall( type T ) _Atomic const T * ?( _Atomic const T * restrict volatile * ),1092 forall( otype T ) T * ?( T * restrict volatile * ), * ?( T * _Atomic restrict volatile * ); 1093 forall( otype T ) _Atomic T * ?( _Atomic T * restrict volatile * ), * ?( _Atomic T * _Atomic restrict volatile * ); 1094 forall( otype T ) const T * ?( const T * restrict volatile * ), * ?( const T * _Atomic restrict volatile * ); 1095 forall( otype T ) volatile T * ?( volatile T * restrict volatile * ), * ?( volatile T * _Atomic restrict volatile * ); 1096 forall( otype T ) restrict T * ?( restrict T * restrict volatile * ), * ?( restrict T * _Atomic restrict volatile * ); 1097 forall( otype T ) _Atomic const T * ?( _Atomic const T * restrict volatile * ), 1099 1098 * ?( _Atomic const T * _Atomic restrict volatile * ); 1100 forall( type T ) _Atomic restrict T * ?( _Atomic restrict T * restrict volatile * ),1099 forall( otype T ) _Atomic restrict T * ?( _Atomic restrict T * restrict volatile * ), 1101 1100 * ?( _Atomic restrict T * _Atomic restrict volatile * ); 1102 forall( type T ) _Atomic volatile T * ?( _Atomic volatile T * restrict volatile * ),1101 forall( otype T ) _Atomic volatile T * ?( _Atomic volatile T * restrict volatile * ), 1103 1102 * ?( _Atomic volatile T * _Atomic restrict volatile * ); 1104 forall( type T ) const restrict T * ?( const restrict T * restrict volatile * ),1103 forall( otype T ) const restrict T * ?( const restrict T * restrict volatile * ), 1105 1104 * ?( const restrict T * _Atomic restrict volatile * ); 1106 forall( type T ) const volatile T * ?( const volatile T * restrict volatile * ),1105 forall( otype T ) const volatile T * ?( const volatile T * restrict volatile * ), 1107 1106 * ?( const volatile T * _Atomic restrict volatile * ); 1108 forall( type T ) restrict volatile T * ?( restrict volatile T * restrict volatile * ),1107 forall( otype T ) restrict volatile T * ?( restrict volatile T * restrict volatile * ), 1109 1108 * ?( restrict volatile T * _Atomic restrict volatile * ); 1110 forall( type T ) _Atomic const restrict T * ?( _Atomic const restrict T * restrict volatile * ),1109 forall( otype T ) _Atomic const restrict T * ?( _Atomic const restrict T * restrict volatile * ), 1111 1110 * ?( _Atomic const restrict T * _Atomic restrict volatile * ); 1112 forall( type T ) _Atomic const volatile T * ?( _Atomic const volatile T * restrict volatile * ),1111 forall( otype T ) _Atomic const volatile T * ?( _Atomic const volatile T * restrict volatile * ), 1113 1112 * ?( _Atomic const volatile T * _Atomic restrict volatile * ); 1114 forall( type T ) _Atomic restrict volatile T * ?( _Atomic restrict volatile T * restrict volatile * ),1113 forall( otype T ) _Atomic restrict volatile T * ?( _Atomic restrict volatile T * restrict volatile * ), 1115 1114 * ?( _Atomic restrict volatile T * _Atomic restrict volatile * ); 1116 forall( type T ) const restrict volatile T * ?( const restrict volatile T * restrict volatile * ),1115 forall( otype T ) const restrict volatile T * ?( const restrict volatile T * restrict volatile * ), 1117 1116 * ?( const restrict volatile T * _Atomic restrict volatile * ); 1118 forall( type T ) _Atomic const restrict volatile T * ?( _Atomic const restrict volatile T * restrict volatile * ),1117 forall( otype T ) _Atomic const restrict volatile T * ?( _Atomic const restrict volatile T * restrict volatile * ), 1119 1118 * ?( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1120 1119 \end{lstlisting} … … 1195 1194 The expression would be valid if \lstinline$?++$ were declared by 1196 1195 \begin{lstlisting} 1197 forall( type T ) T * ?++( T * * );1196 forall( otype T ) T * ?++( T * * ); 1198 1197 \end{lstlisting} with \lstinline$T$ inferred to be \lstinline$char$. 1199 1198 … … 1203 1202 Hence the actual predefined function is 1204 1203 \begin{lstlisting} 1205 forall( type T ) T * ?++( T * restrict volatile * );1204 forall( otype T ) T * ?++( T * restrict volatile * ); 1206 1205 \end{lstlisting} which also accepts a \lstinline$char * *$ argument, because of the safe conversions that add 1207 1206 \lstinline$volatile$ and \lstinline$restrict$ qualifiers. (The parameter is not constqualified, so constant pointers cannot be incremented.) … … 1217 1216 \lstinline$char const volatile *$, so a new overloading is needed: 1218 1217 \begin{lstlisting} 1219 forall( type T ) T const volatile * ?++( T const volatile *restrict volatile * );1218 forall( otype T ) T const volatile * ?++( T const volatile *restrict volatile * ); 1220 1219 \end{lstlisting} 1221 1220 One overloading is needed for each combination of qualifiers in the pointedat type\index{deficiencies!pointers to qualified types}. … … 1225 1224 The \lstinline$restrict$ qualifier is handled just like \lstinline$const$ and \lstinline$volatile$ in the previous case: 1226 1225 \begin{lstlisting} 1227 forall( type T ) T restrict * ?++( T restrict *restrict volatile * );1226 forall( otype T ) T restrict * ?++( T restrict *restrict volatile * ); 1228 1227 \end{lstlisting} with \lstinline$T$ inferred to be \lstinline$float *$. 1229 1228 This looks odd, because {\c11} contains a constraint that requires restrictqualified types to be pointertoobject types, and \lstinline$T$ is not syntactically a pointer type. \CFA loosens the constraint. … … 1283 1282 long double ++?( volatile long double * ), ++?( _Atomic volatile long double * ); 1284 1283 1285 forall( type T ) T * ++?( T * restrict volatile * ), * ++?( T * _Atomic restrict volatile * );1286 forall( type T ) _Atomic T * ++?( _Atomic T * restrict volatile * ), * ++?( _Atomic T * _Atomic restrict volatile * );1287 forall( type T ) const T * ++?( const T * restrict volatile * ), * ++?( const T * _Atomic restrict volatile * );1288 forall( type T ) volatile T * ++?( volatile T * restrict volatile * ), * ++?( volatile T * _Atomic restrict volatile * );1289 forall( type T ) restrict T * ++?( restrict T * restrict volatile * ), * ++?( restrict T * _Atomic restrict volatile * );1290 forall( type T ) _Atomic const T * ++?( _Atomic const T * restrict volatile * ),1284 forall( otype T ) T * ++?( T * restrict volatile * ), * ++?( T * _Atomic restrict volatile * ); 1285 forall( otype T ) _Atomic T * ++?( _Atomic T * restrict volatile * ), * ++?( _Atomic T * _Atomic restrict volatile * ); 1286 forall( otype T ) const T * ++?( const T * restrict volatile * ), * ++?( const T * _Atomic restrict volatile * ); 1287 forall( otype T ) volatile T * ++?( volatile T * restrict volatile * ), * ++?( volatile T * _Atomic restrict volatile * ); 1288 forall( otype T ) restrict T * ++?( restrict T * restrict volatile * ), * ++?( restrict T * _Atomic restrict volatile * ); 1289 forall( otype T ) _Atomic const T * ++?( _Atomic const T * restrict volatile * ), 1291 1290 * ++?( _Atomic const T * _Atomic restrict volatile * ); 1292 forall( type T ) _Atomic volatile T * ++?( _Atomic volatile T * restrict volatile * ),1291 forall( otype T ) _Atomic volatile T * ++?( _Atomic volatile T * restrict volatile * ), 1293 1292 * ++?( _Atomic volatile T * _Atomic restrict volatile * ); 1294 forall( type T ) _Atomic restrict T * ++?( _Atomic restrict T * restrict volatile * ),1293 forall( otype T ) _Atomic restrict T * ++?( _Atomic restrict T * restrict volatile * ), 1295 1294 * ++?( _Atomic restrict T * _Atomic restrict volatile * ); 1296 forall( type T ) const volatile T * ++?( const volatile T * restrict volatile * ),1295 forall( otype T ) const volatile T * ++?( const volatile T * restrict volatile * ), 1297 1296 * ++?( const volatile T * _Atomic restrict volatile * ); 1298 forall( type T ) const restrict T * ++?( const restrict T * restrict volatile * ),1297 forall( otype T ) const restrict T * ++?( const restrict T * restrict volatile * ), 1299 1298 * ++?( const restrict T * _Atomic restrict volatile * ); 1300 forall( type T ) restrict volatile T * ++?( restrict volatile T * restrict volatile * ),1299 forall( otype T ) restrict volatile T * ++?( restrict volatile T * restrict volatile * ), 1301 1300 * ++?( restrict volatile T * _Atomic restrict volatile * ); 1302 forall( type T ) _Atomic const volatile T * ++?( _Atomic const volatile T * restrict volatile * ),1301 forall( otype T ) _Atomic const volatile T * ++?( _Atomic const volatile T * restrict volatile * ), 1303 1302 * ++?( _Atomic const volatile T * _Atomic restrict volatile * ); 1304 forall( type T ) _Atomic const restrict T * ++?( _Atomic const restrict T * restrict volatile * ),1303 forall( otype T ) _Atomic const restrict T * ++?( _Atomic const restrict T * restrict volatile * ), 1305 1304 * ++?( _Atomic const restrict T * _Atomic restrict volatile * ); 1306 forall( type T ) _Atomic restrict volatile T * ++?( _Atomic restrict volatile T * restrict volatile * ),1305 forall( otype T ) _Atomic restrict volatile T * ++?( _Atomic restrict volatile T * restrict volatile * ), 1307 1306 * ++?( _Atomic restrict volatile T * _Atomic restrict volatile * ); 1308 forall( type T ) const restrict volatile T * ++?( const restrict volatile T * restrict volatile * ),1307 forall( otype T ) const restrict volatile T * ++?( const restrict volatile T * restrict volatile * ), 1309 1308 * ++?( const restrict volatile T * _Atomic restrict volatile * ); 1310 forall( type T ) _Atomic const restrict volatile T * ++?( _Atomic const restrict volatile T * restrict volatile * ),1309 forall( otype T ) _Atomic const restrict volatile T * ++?( _Atomic const restrict volatile T * restrict volatile * ), 1311 1310 * ++?( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1312 1311 … … 1327 1326 long double ?( volatile long double * ), ?( _Atomic volatile long double * ); 1328 1327 1329 forall( type T ) T * ?( T * restrict volatile * ), * ?( T * _Atomic restrict volatile * );1330 forall( type T ) _Atomic T * ?( _Atomic T * restrict volatile * ), * ?( _Atomic T * _Atomic restrict volatile * );1331 forall( type T ) const T * ?( const T * restrict volatile * ), * ?( const T * _Atomic restrict volatile * );1332 forall( type T ) volatile T * ?( volatile T * restrict volatile * ), * ?( volatile T * _Atomic restrict volatile * );1333 forall( type T ) restrict T * ?( restrict T * restrict volatile * ), * ?( restrict T * _Atomic restrict volatile * );1334 forall( type T ) _Atomic const T * ?( _Atomic const T * restrict volatile * ),1328 forall( otype T ) T * ?( T * restrict volatile * ), * ?( T * _Atomic restrict volatile * ); 1329 forall( otype T ) _Atomic T * ?( _Atomic T * restrict volatile * ), * ?( _Atomic T * _Atomic restrict volatile * ); 1330 forall( otype T ) const T * ?( const T * restrict volatile * ), * ?( const T * _Atomic restrict volatile * ); 1331 forall( otype T ) volatile T * ?( volatile T * restrict volatile * ), * ?( volatile T * _Atomic restrict volatile * ); 1332 forall( otype T ) restrict T * ?( restrict T * restrict volatile * ), * ?( restrict T * _Atomic restrict volatile * ); 1333 forall( otype T ) _Atomic const T * ?( _Atomic const T * restrict volatile * ), 1335 1334 * ?( _Atomic const T * _Atomic restrict volatile * ); 1336 forall( type T ) _Atomic volatile T * ?( _Atomic volatile T * restrict volatile * ),1335 forall( otype T ) _Atomic volatile T * ?( _Atomic volatile T * restrict volatile * ), 1337 1336 * ?( _Atomic volatile T * _Atomic restrict volatile * ); 1338 forall( type T ) _Atomic restrict T * ?( _Atomic restrict T * restrict volatile * ),1337 forall( otype T ) _Atomic restrict T * ?( _Atomic restrict T * restrict volatile * ), 1339 1338 * ?( _Atomic restrict T * _Atomic restrict volatile * ); 1340 forall( type T ) const volatile T * ?( const volatile T * restrict volatile * ),1339 forall( otype T ) const volatile T * ?( const volatile T * restrict volatile * ), 1341 1340 * ?( const volatile T * _Atomic restrict volatile * ); 1342 forall( type T ) const restrict T * ?( const restrict T * restrict volatile * ),1341 forall( otype T ) const restrict T * ?( const restrict T * restrict volatile * ), 1343 1342 * ?( const restrict T * _Atomic restrict volatile * ); 1344 forall( type T ) restrict volatile T * ?( restrict volatile T * restrict volatile * ),1343 forall( otype T ) restrict volatile T * ?( restrict volatile T * restrict volatile * ), 1345 1344 * ?( restrict volatile T * _Atomic restrict volatile * ); 1346 forall( type T ) _Atomic const volatile T * ?( _Atomic const volatile T * restrict volatile * ),1345 forall( otype T ) _Atomic const volatile T * ?( _Atomic const volatile T * restrict volatile * ), 1347 1346 * ?( _Atomic const volatile T * _Atomic restrict volatile * ); 1348 forall( type T ) _Atomic const restrict T * ?( _Atomic const restrict T * restrict volatile * ),1347 forall( otype T ) _Atomic const restrict T * ?( _Atomic const restrict T * restrict volatile * ), 1349 1348 * ?( _Atomic const restrict T * _Atomic restrict volatile * ); 1350 forall( type T ) _Atomic restrict volatile T * ?( _Atomic restrict volatile T * restrict volatile * ),1349 forall( otype T ) _Atomic restrict volatile T * ?( _Atomic restrict volatile T * restrict volatile * ), 1351 1350 * ?( _Atomic restrict volatile T * _Atomic restrict volatile * ); 1352 forall( type T ) const restrict volatile T * ?( const restrict volatile T * restrict volatile * ),1351 forall( otype T ) const restrict volatile T * ?( const restrict volatile T * restrict volatile * ), 1353 1352 * ?( const restrict volatile T * _Atomic restrict volatile * ); 1354 forall( type T ) _Atomic const restrict volatile T * ?( _Atomic const restrict volatile T * restrict volatile * ),1353 forall( otype T ) _Atomic const restrict volatile T * ?( _Atomic const restrict volatile T * restrict volatile * ), 1355 1354 * ?( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1356 1355 \end{lstlisting} … … 1380 1379 \predefined 1381 1380 \begin{lstlisting} 1382 forall( type T ) lvalue T *?( T * );1383 forall( type T ) _Atomic lvalue T *?( _Atomic T * );1384 forall( type T ) const lvalue T *?( const T * );1385 forall( type T ) volatile lvalue T *?( volatile T * );1386 forall( type T ) restrict lvalue T *?( restrict T * );1387 forall( type T ) _Atomic const lvalue T *?( _Atomic const T * );1388 forall( type T ) _Atomic volatile lvalue T *?( _Atomic volatile T * );1389 forall( type T ) _Atomic restrict lvalue T *?( _Atomic restrict T * );1390 forall( type T ) const volatile lvalue T *?( const volatile T * );1391 forall( type T ) const restrict lvalue T *?( const restrict T * );1392 forall( type T ) restrict volatile lvalue T *?( restrict volatile T * );1393 forall( type T ) _Atomic const volatile lvalue T *?( _Atomic const volatile T * );1394 forall( type T ) _Atomic const restrict lvalue T *?( _Atomic const restrict T * );1395 forall( type T ) _Atomic restrict volatile lvalue T *?( _Atomic restrict volatile T * );1396 forall( type T ) const restrict volatile lvalue T *?( const restrict volatile T * );1397 forall( type T ) _Atomic const restrict volatile lvalue T *?( _Atomic const restrict volatile T * );1381 forall( otype T ) lvalue T *?( T * ); 1382 forall( otype T ) _Atomic lvalue T *?( _Atomic T * ); 1383 forall( otype T ) const lvalue T *?( const T * ); 1384 forall( otype T ) volatile lvalue T *?( volatile T * ); 1385 forall( otype T ) restrict lvalue T *?( restrict T * ); 1386 forall( otype T ) _Atomic const lvalue T *?( _Atomic const T * ); 1387 forall( otype T ) _Atomic volatile lvalue T *?( _Atomic volatile T * ); 1388 forall( otype T ) _Atomic restrict lvalue T *?( _Atomic restrict T * ); 1389 forall( otype T ) const volatile lvalue T *?( const volatile T * ); 1390 forall( otype T ) const restrict lvalue T *?( const restrict T * ); 1391 forall( otype T ) restrict volatile lvalue T *?( restrict volatile T * ); 1392 forall( otype T ) _Atomic const volatile lvalue T *?( _Atomic const volatile T * ); 1393 forall( otype T ) _Atomic const restrict lvalue T *?( _Atomic const restrict T * ); 1394 forall( otype T ) _Atomic restrict volatile lvalue T *?( _Atomic restrict volatile T * ); 1395 forall( otype T ) const restrict volatile lvalue T *?( const restrict volatile T * ); 1396 forall( otype T ) _Atomic const restrict volatile lvalue T *?( _Atomic const restrict volatile T * ); 1398 1397 forall( ftype FT ) FT *?( FT * ); 1399 1398 \end{lstlisting} … … 1510 1509 \begin{rationale} 1511 1510 \begin{lstlisting} 1512 type Pair = struct { int first, second; };1511 otype Pair = struct { int first, second; }; 1513 1512 size_t p_size = sizeof(Pair); // constant expression 1514 extern type Rational;@\use{Rational}@1513 extern otype Rational;@\use{Rational}@ 1515 1514 size_t c_size = sizeof(Rational); // nonconstant expression 1516 1515 forall(type T) T f(T p1, T p2) { … … 1636 1635 Consider 1637 1636 \begin{lstlisting} 1638 forall( type T  T ?*?( T, T ) ) T square( T );1637 forall( otype T  T ?*?( T, T ) ) T square( T ); 1639 1638 short s; 1640 1639 square( s ); … … 1647 1646 A more troubling example is 1648 1647 \begin{lstlisting} 1649 forall( type T  ?*?( T, T ) ) T product( T[], int n );1648 forall( otype T  ?*?( T, T ) ) T product( T[], int n ); 1650 1649 short sa[5]; 1651 1650 product( sa, 5); … … 1704 1703 ?+?( _Complex long double, _Complex long double ), ??( _Complex long double, _Complex long double ); 1705 1704 1706 forall( type T ) T * ?+?( T *, ptrdiff_t ), * ?+?( ptrdiff_t, T * ), * ??( T *, ptrdiff_t );1707 forall( type T ) _Atomic T * ?+?( _Atomic T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic T * ),1705 forall( otype T ) T * ?+?( T *, ptrdiff_t ), * ?+?( ptrdiff_t, T * ), * ??( T *, ptrdiff_t ); 1706 forall( otype T ) _Atomic T * ?+?( _Atomic T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic T * ), 1708 1707 * ??( _Atomic T *, ptrdiff_t ); 1709 forall( type T ) const T * ?+?( const T *, ptrdiff_t ), * ?+?( ptrdiff_t, const T * ),1708 forall( otype T ) const T * ?+?( const T *, ptrdiff_t ), * ?+?( ptrdiff_t, const T * ), 1710 1709 * ??( const T *, ptrdiff_t ); 1711 forall( type T ) restrict T * ?+?( restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, restrict T * ),1710 forall( otype T ) restrict T * ?+?( restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, restrict T * ), 1712 1711 * ??( restrict T *, ptrdiff_t ); 1713 forall( type T ) volatile T * ?+?( volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, volatile T * ),1712 forall( otype T ) volatile T * ?+?( volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, volatile T * ), 1714 1713 * ??( volatile T *, ptrdiff_t ); 1715 forall( type T ) _Atomic const T * ?+?( _Atomic const T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic const T * ),1714 forall( otype T ) _Atomic const T * ?+?( _Atomic const T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic const T * ), 1716 1715 * ??( _Atomic const T *, ptrdiff_t ); 1717 forall( type T ) _Atomic restrict T * ?+?( _Atomic restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic restrict T * ),1716 forall( otype T ) _Atomic restrict T * ?+?( _Atomic restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic restrict T * ), 1718 1717 * ??( _Atomic restrict T *, ptrdiff_t ); 1719 forall( type T ) _Atomic volatile T * ?+?( _Atomic volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic volatile T * ),1718 forall( otype T ) _Atomic volatile T * ?+?( _Atomic volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, _Atomic volatile T * ), 1720 1719 * ??( _Atomic volatile T *, ptrdiff_t ); 1721 forall( type T ) const restrict T * ?+?( const restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, const restrict T * ),1720 forall( otype T ) const restrict T * ?+?( const restrict T *, ptrdiff_t ), * ?+?( ptrdiff_t, const restrict T * ), 1722 1721 * ??( const restrict T *, ptrdiff_t ); 1723 forall( type T ) const volatile T * ?+?( const volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, const volatile T * ),1722 forall( otype T ) const volatile T * ?+?( const volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, const volatile T * ), 1724 1723 * ??( const volatile T *, ptrdiff_t ); 1725 forall( type T ) restrict volatile T * ?+?( restrict volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, restrict volatile T * ),1724 forall( otype T ) restrict volatile T * ?+?( restrict volatile T *, ptrdiff_t ), * ?+?( ptrdiff_t, restrict volatile T * ), 1726 1725 * ??( restrict volatile T *, ptrdiff_t ); 1727 forall( type T ) _Atomic const restrict T * ?+?( _Atomic const restrict T *, ptrdiff_t ),1726 forall( otype T ) _Atomic const restrict T * ?+?( _Atomic const restrict T *, ptrdiff_t ), 1728 1727 * ?+?( ptrdiff_t, _Atomic const restrict T * ), 1729 1728 * ??( _Atomic const restrict T *, ptrdiff_t ); 1730 forall( type T ) ptrdiff_t1729 forall( otype T ) ptrdiff_t 1731 1730 * ??( const restrict volatile T *, const restrict volatile T * ), 1732 1731 * ??( _Atomic const restrict volatile T *, _Atomic const restrict volatile T * ); … … 2052 2051 2053 2052 \begin{lstlisting} 2054 extern type Rational;@\use{Rational}@2053 extern otype Rational;@\use{Rational}@ 2055 2054 extern const Rational 0;@\use{0}@ 2056 2055 extern int ?!=?( Rational, Rational ); … … 2095 2094 If the second and third operands both have interpretations with non\lstinline$void$ types, the expression is treated as if it were the call ``\lstinline$cond((a)!=0, b, c)$'', with \lstinline$cond$ declared as 2096 2095 \begin{lstlisting} 2097 forall( type T ) T cond( int, T, T );2096 forall( otype T ) T cond( int, T, T ); 2098 2097 forall( dtype D ) void * cond( int, D *, void * ), * cond( int, void *, D * ); 2099 2098 forall( dtype D ) _atomic void * cond( … … 2455 2454 \predefined 2456 2455 \begin{lstlisting} 2457 forall( type T ) T2456 forall( otype T ) T 2458 2457 * ?+=?( T * restrict volatile *, ptrdiff_t ), 2459 2458 * ?=?( T * restrict volatile *, ptrdiff_t ), 2460 2459 * ?+=?( T * _Atomic restrict volatile *, ptrdiff_t ), 2461 2460 * ?=?( T * _Atomic restrict volatile *, ptrdiff_t ); 2462 forall( type T ) T _Atomic2461 forall( otype T ) T _Atomic 2463 2462 * ?+=?( T _Atomic * restrict volatile *, ptrdiff_t ), 2464 2463 * ?=?( T _Atomic * restrict volatile *, ptrdiff_t ), 2465 2464 * ?+=?( T _Atomic * _Atomic restrict volatile *, ptrdiff_t ), 2466 2465 * ?=?( T _Atomic * _Atomic restrict volatile *, ptrdiff_t ); 2467 forall( type T ) T const2466 forall( otype T ) T const 2468 2467 * ?+=?( T const * restrict volatile *, ptrdiff_t ), 2469 2468 * ?=?( T const * restrict volatile *, ptrdiff_t ), 2470 2469 * ?+=?( T const * _Atomic restrict volatile *, ptrdiff_t ), 2471 2470 * ?=?( T const * _Atomic restrict volatile *, ptrdiff_t ); 2472 forall( type T ) T restrict2471 forall( otype T ) T restrict 2473 2472 * ?+=?( T restrict * restrict volatile *, ptrdiff_t ), 2474 2473 * ?=?( T restrict * restrict volatile *, ptrdiff_t ), 2475 2474 * ?+=?( T restrict * _Atomic restrict volatile *, ptrdiff_t ), 2476 2475 * ?=?( T restrict * _Atomic restrict volatile *, ptrdiff_t ); 2477 forall( type T ) T volatile2476 forall( otype T ) T volatile 2478 2477 * ?+=?( T volatile * restrict volatile *, ptrdiff_t ), 2479 2478 * ?=?( T volatile * restrict volatile *, ptrdiff_t ), 2480 2479 * ?+=?( T volatile * _Atomic restrict volatile *, ptrdiff_t ), 2481 2480 * ?=?( T volatile * _Atomic restrict volatile *, ptrdiff_t ); 2482 forall( type T ) T _Atomic const2481 forall( otype T ) T _Atomic const 2483 2482 * ?+=?( T _Atomic const restrict volatile *, ptrdiff_t ), 2484 2483 * ?=?( T _Atomic const restrict volatile *, ptrdiff_t ), 2485 2484 * ?+=?( T _Atomic const _Atomic restrict volatile *, ptrdiff_t ), 2486 2485 * ?=?( T _Atomic const _Atomic restrict volatile *, ptrdiff_t ); 2487 forall( type T ) T _Atomic restrict2486 forall( otype T ) T _Atomic restrict 2488 2487 * ?+=?( T _Atomic restrict * restrict volatile *, ptrdiff_t ), 2489 2488 * ?=?( T _Atomic restrict * restrict volatile *, ptrdiff_t ), 2490 2489 * ?+=?( T _Atomic restrict * _Atomic restrict volatile *, ptrdiff_t ), 2491 2490 * ?=?( T _Atomic restrict * _Atomic restrict volatile *, ptrdiff_t ); 2492 forall( type T ) T _Atomic volatile2491 forall( otype T ) T _Atomic volatile 2493 2492 * ?+=?( T _Atomic volatile * restrict volatile *, ptrdiff_t ), 2494 2493 * ?=?( T _Atomic volatile * restrict volatile *, ptrdiff_t ), 2495 2494 * ?+=?( T _Atomic volatile * _Atomic restrict volatile *, ptrdiff_t ), 2496 2495 * ?=?( T _Atomic volatile * _Atomic restrict volatile *, ptrdiff_t ); 2497 forall( type T ) T const restrict2496 forall( otype T ) T const restrict 2498 2497 * ?+=?( T const restrict * restrict volatile *, ptrdiff_t ), 2499 2498 * ?=?( T const restrict * restrict volatile *, ptrdiff_t ), 2500 2499 * ?+=?( T const restrict * _Atomic restrict volatile *, ptrdiff_t ), 2501 2500 * ?=?( T const restrict * _Atomic restrict volatile *, ptrdiff_t ); 2502 forall( type T ) T const volatile2501 forall( otype T ) T const volatile 2503 2502 * ?+=?( T const volatile * restrict volatile *, ptrdiff_t ), 2504 2503 * ?=?( T const volatile * restrict volatile *, ptrdiff_t ), 2505 2504 * ?+=?( T const volatile * _Atomic restrict volatile *, ptrdiff_t ), 2506 2505 * ?=?( T const volatile * _Atomic restrict volatile *, ptrdiff_t ); 2507 forall( type T ) T restrict volatile2506 forall( otype T ) T restrict volatile 2508 2507 * ?+=?( T restrict volatile * restrict volatile *, ptrdiff_t ), 2509 2508 * ?=?( T restrict volatile * restrict volatile *, ptrdiff_t ), 2510 2509 * ?+=?( T restrict volatile * _Atomic restrict volatile *, ptrdiff_t ), 2511 2510 * ?=?( T restrict volatile * _Atomic restrict volatile *, ptrdiff_t ); 2512 forall( type T ) T _Atomic const restrict2511 forall( otype T ) T _Atomic const restrict 2513 2512 * ?+=?( T _Atomic const restrict * restrict volatile *, ptrdiff_t ), 2514 2513 * ?=?( T _Atomic const restrict * restrict volatile *, ptrdiff_t ), 2515 2514 * ?+=?( T _Atomic const restrict * _Atomic restrict volatile *, ptrdiff_t ), 2516 2515 * ?=?( T _Atomic const restrict * _Atomic restrict volatile *, ptrdiff_t ); 2517 forall( type T ) T _Atomic const volatile2516 forall( otype T ) T _Atomic const volatile 2518 2517 * ?+=?( T _Atomic const volatile * restrict volatile *, ptrdiff_t ), 2519 2518 * ?=?( T _Atomic const volatile * restrict volatile *, ptrdiff_t ), 2520 2519 * ?+=?( T _Atomic const volatile * _Atomic restrict volatile *, ptrdiff_t ), 2521 2520 * ?=?( T _Atomic const volatile * _Atomic restrict volatile *, ptrdiff_t ); 2522 forall( type T ) T _Atomic restrict volatile2521 forall( otype T ) T _Atomic restrict volatile 2523 2522 * ?+=?( T _Atomic restrict volatile * restrict volatile *, ptrdiff_t ), 2524 2523 * ?=?( T _Atomic restrict volatile * restrict volatile *, ptrdiff_t ), 2525 2524 * ?+=?( T _Atomic restrict volatile * _Atomic restrict volatile *, ptrdiff_t ), 2526 2525 * ?=?( T _Atomic restrict volatile * _Atomic restrict volatile *, ptrdiff_t ); 2527 forall( type T ) T const restrict volatile2526 forall( otype T ) T const restrict volatile 2528 2527 * ?+=?( T const restrict volatile * restrict volatile *, ptrdiff_t ), 2529 2528 * ?=?( T const restrict volatile * restrict volatile *, ptrdiff_t ), 2530 2529 * ?+=?( T const restrict volatile * _Atomic restrict volatile *, ptrdiff_t ), 2531 2530 * ?=?( T const restrict volatile * _Atomic restrict volatile *, ptrdiff_t ); 2532 forall( type T ) T _Atomic const restrict volatile2531 forall( otype T ) T _Atomic const restrict volatile 2533 2532 * ?+=?( T _Atomic const restrict volatile * restrict volatile *, ptrdiff_t ), 2534 2533 * ?=?( T _Atomic const restrict volatile * restrict volatile *, ptrdiff_t ), … … 2842 2841 This sort of declaration is illegal because the scope of the type identifiers ends at the end of the declaration, but the scope of the structure tag does not. 2843 2842 \begin{lstlisting} 2844 forall( type T ) struct Pair { T a, b;2843 forall( otype T ) struct Pair { T a, b; 2845 2844 } mkPair( T, T ); // illegal 2846 2845 \end{lstlisting} … … 2867 2866 If this restriction were lifted, it would be possible to write 2868 2867 \begin{lstlisting} 2869 forall( type T ) T * alloc( void );@\use{alloc}@ int *p = alloc();2868 forall( otype T ) T * alloc( void );@\use{alloc}@ int *p = alloc(); 2870 2869 \end{lstlisting} 2871 2870 Here \lstinline$alloc()$ would receive \lstinline$int$ as an inferred argument, and return an … … 2876 2875 \lstinline$T$: 2877 2876 \begin{lstlisting} 2878 forall( type T ) T * alloc( T initial_value );@\use{alloc}@2877 forall( otype T ) T * alloc( T initial_value );@\use{alloc}@ 2879 2878 \end{lstlisting} 2880 2879 \end{rationale} … … 2899 2898 \begin{lstlisting} 2900 2899 int fi( int ); 2901 forall( type T ) T fT( T );2900 forall( otype T ) T fT( T ); 2902 2901 \end{lstlisting} 2903 2902 \lstinline$fi()$ takes an \lstinline$int$ and returns an \lstinline$int$. \lstinline$fT()$ takes a … … 2905 2904 \begin{lstlisting} 2906 2905 int (*pfi )( int ) = fi; 2907 forall( type T ) T (*pfT )( T ) = fT;2906 forall( otype T ) T (*pfT )( T ) = fT; 2908 2907 \end{lstlisting} 2909 2908 \lstinline$pfi$ and \lstinline$pfT$ are pointers to functions. \lstinline$pfT$ is not polymorphic, but the function it points at is. … … 2912 2911 return pfi; 2913 2912 } 2914 forall( type T ) T (*fvpfT( void ))( T ) {2913 forall( otype T ) T (*fvpfT( void ))( T ) { 2915 2914 return pfT; 2916 2915 } … … 2918 2917 \lstinline$fvpfi()$ and \lstinline$fvpfT()$ are functions taking no arguments and returning pointers to functions. \lstinline$fvpfT()$ is monomorphic, but the function that its return value points at is polymorphic. 2919 2918 \begin{lstlisting} 2920 forall( type T ) int ( *fTpfi( T ) )( int );2921 forall( type T ) T ( *fTpfT( T ) )( T );2922 forall( type T,type U ) U ( *fTpfU( T ) )( U );2919 forall( otype T ) int ( *fTpfi( T ) )( int ); 2920 forall( otype T ) T ( *fTpfT( T ) )( T ); 2921 forall( otype T, otype U ) U ( *fTpfU( T ) )( U ); 2923 2922 \end{lstlisting} 2924 2923 \lstinline$fTpfi()$ is a polymorphic function that returns a pointer to a monomorphic function taking an integer and returning an integer. … … 2930 2929 \lstinline$char *$. 2931 2930 \begin{lstlisting} 2932 forall( type T, type U,type V ) U * f( T *, U, V * const );2933 forall( type U, type V,type W ) U * g( V *, U, W * const );2931 forall( otype T, otype U, otype V ) U * f( T *, U, V * const ); 2932 forall( otype U, otype V, otype W ) U * g( V *, U, W * const ); 2934 2933 \end{lstlisting} 2935 2934 The functions \lstinline$f()$ and \lstinline$g()$ have compatible types. … … 2939 2938 Replacing every \(f_i\) by \(g_i\) in \(f\) gives 2940 2939 \begin{lstlisting} 2941 forall( type V, type U,type W ) U * f( V *, U, W * const );2940 forall( otype V, otype U, otype W ) U * f( V *, U, W * const ); 2942 2941 \end{lstlisting} which has a return type and parameter list that is compatible with \(g\). 2943 2942 \begin{rationale} … … 3127 3126 \examples 3128 3127 \begin{lstlisting} 3129 forall( type T  T ?*?( T, T ))@\use{?*?}@3128 forall( otype T  T ?*?( T, T ))@\use{?*?}@ 3130 3129 T square( T val ) {@\impl{square}@ 3131 3130 return val + val; 3132 3131 } 3133 context summable(type T ) {@\impl{summable}@3132 trait summable( otype T ) {@\impl{summable}@ 3134 3133 T ?+=?( T *, T );@\use{?+=?}@ 3135 3134 const T 0;@\use{0}@ 3136 3135 }; 3137 context list_of( type List,type Element ) {@\impl{list_of}@3136 trait list_of( otype List, otype Element ) {@\impl{list_of}@ 3138 3137 Element car( List ); 3139 3138 List cdr( List ); … … 3142 3141 int is_nil( List ); 3143 3142 }; 3144 context sum_list( type List,type Element  summable( Element )  list_of( List, Element ) ) {};3143 trait sum_list( otype List, otype Element  summable( Element )  list_of( List, Element ) ) {}; 3145 3144 \end{lstlisting} 3146 3145 \lstinline$sum_list$ contains seven declarations, which describe a list whose elements can be added up. … … 3204 3203 Incomplete type declarations allow compact mutuallyrecursive types. 3205 3204 \begin{lstlisting} 3206 type t1; // incomplete type declaration3207 type t2 = struct { t1 * p; ... };3208 type t1 = struct { t2 * p; ... };3205 otype t1; // incomplete type declaration 3206 otype t2 = struct { t1 * p; ... }; 3207 otype t1 = struct { t2 * p; ... }; 3209 3208 \end{lstlisting} 3210 3209 Without them, mutual recursion could be handled by declaring mutually recursive structures, then initializing the types to those structures. 3211 3210 \begin{lstlisting} 3212 3211 struct s1; 3213 type t2 = struct s2 { struct s1 * p; ... };3214 type t1 = struct s1 { struct s2 * p; ... };3212 otype t2 = struct s2 { struct s1 * p; ... }; 3213 otype t1 = struct s1 { struct s2 * p; ... }; 3215 3214 \end{lstlisting} 3216 3215 This introduces extra names, and may force the programmer to cast between the types and their implementations. … … 3267 3266 This prevents the declaration of types that contain each other. 3268 3267 \begin{lstlisting} 3269 type t1;3270 type t2 = t1; // illegal: incomplete type t13271 type t1 = t2;3268 otype t1; 3269 otype t2 = t1; // illegal: incomplete type t1 3270 otype t1 = t2; 3272 3271 \end{lstlisting} 3273 3272 … … 3276 3275 types}. 3277 3276 \begin{lstlisting} 3278 extern type Huge; // extendedprecision integer type3279 type Rational = struct {3277 extern otype Huge; // extendedprecision integer type 3278 otype Rational = struct { 3280 3279 Huge numerator, denominator; // illegal 3281 3280 }; … … 3316 3315 \begin{lstlisting} 3317 3316 #include <stdlib.h> 3318 T * new( type T ) { return ( T * )malloc( sizeof( T) ); };3317 T * new( otype T ) { return ( T * )malloc( sizeof( T) ); }; 3319 3318 @\ldots@ int * ip = new( int ); 3320 3319 \end{lstlisting} … … 3327 3326 Since type declarations create new types, instances of types are always passed by value. 3328 3327 \begin{lstlisting} 3329 type A1 = int[2];3328 otype A1 = int[2]; 3330 3329 void f1( A1 a ) { a[0] = 0; }; 3331 typedef int A2[2];3330 otypedef int A2[2]; 3332 3331 void f2( A2 a ) { a[0] = 0; }; 3333 3332 A1 v1; … … 3346 3345 That unit might contain the declarations 3347 3346 \begin{lstlisting} 3348 type Complex = struct { float re, im; };@\impl{Complex}@3347 otype Complex = struct { float re, im; };@\impl{Complex}@ 3349 3348 Complex cplx_i = { 0.0, 1.0 };@\impl{cplx_i}@ 3350 3349 float abs( Complex c ) {@\impl{abs( Complex )}@ … … 3355 3354 3356 3355 \begin{lstlisting} 3357 type Time_of_day = int;@\impl{Time_of_day}@ // seconds since midnight.3356 otype Time_of_day = int;@\impl{Time_of_day}@ // seconds since midnight. 3358 3357 Time_of_day ?+?( Time_of_day t1, int seconds ) {@\impl{?+?}@ 3359 3358 return (( int)t1 + seconds ) % 86400; … … 3429 3428 \examples 3430 3429 \begin{lstlisting} 3431 context s(type T ) {3430 trait s( otype T ) { 3432 3431 T a, b; 3433 3432 } struct impl { int left, right; } a = { 0, 0 }; 3434 type Pair  s( Pair ) = struct impl;3433 otype Pair  s( Pair ) = struct impl; 3435 3434 Pair b = { 1, 1 }; 3436 3435 \end{lstlisting} … … 3440 3439 \lstinline$Pair b$ is compulsory because there is no \lstinline$struct impl b$ to construct a value from. 3441 3440 \begin{lstlisting} 3442 context ss(type T ) {3441 trait ss( otype T ) { 3443 3442 T clone( T ); 3444 3443 void munge( T * ); 3445 3444 } 3446 type Whatsit  ss( Whatsit );@\use{Whatsit}@3447 type Doodad  ss( Doodad ) = struct doodad {@\use{Doodad}@3445 otype Whatsit  ss( Whatsit );@\use{Whatsit}@ 3446 otype Doodad  ss( Doodad ) = struct doodad {@\use{Doodad}@ 3448 3447 Whatsit; // anonymous member 3449 3448 int extra; … … 3466 3465 Default functions and objects are subject to the normal scope rules. 3467 3466 \begin{lstlisting} 3468 type T = @\ldots@;3467 otype T = @\ldots@; 3469 3468 T a_T = @\ldots@; // Default assignment used. 3470 3469 T ?=?( T *, T ); … … 3735 3734 The assertion ``\lstinline$scalar( Complex )$'' should be read as ``type \lstinline$Complex$ is scalar''. 3736 3735 \begin{lstlisting} 3737 context scalar(type T ) {@\impl{scalar}@3736 trait scalar( otype T ) {@\impl{scalar}@ 3738 3737 int !?( T ); 3739 3738 int ?<?( T, T ), ?<=?( T, T ), ?==?( T, T ), ?>=?( T, T ), ?>?( T, T ), ?!=?( T, T ); … … 3745 3744 This is equivalent to inheritance of specifications. 3746 3745 \begin{lstlisting} 3747 context arithmetic(type T  scalar( T ) ) {@\impl{arithmetic}@@\use{scalar}@3746 trait arithmetic( otype T  scalar( T ) ) {@\impl{arithmetic}@@\use{scalar}@ 3748 3747 T +?( T ), ?( T ); 3749 3748 T ?*?( T, T ), ?/?( T, T ), ?+?( T, T ), ??( T, T ); … … 3754 3753 \define{integral types}. 3755 3754 \begin{lstlisting} 3756 context integral(type T  arithmetic( T ) ) {@\impl{integral}@@\use{arithmetic}@3755 trait integral( otype T  arithmetic( T ) ) {@\impl{integral}@@\use{arithmetic}@ 3757 3756 T ~?( T ); 3758 3757 T ?&?( T, T ), ??( T, T ), ?^?( T, T ); … … 3768 3767 The only operation that can be applied to all modifiable lvalues is simple assignment. 3769 3768 \begin{lstlisting} 3770 context m_lvalue(type T ) {@\impl{m_lvalue}@3769 trait m_lvalue( otype T ) {@\impl{m_lvalue}@ 3771 3770 T ?=?( T *, T ); 3772 3771 }; … … 3778 3777 Scalars can also be incremented and decremented. 3779 3778 \begin{lstlisting} 3780 context m_l_scalar(type T  scalar( T )  m_lvalue( T ) ) {@\impl{m_l_scalar}@3779 trait m_l_scalar( otype T  scalar( T )  m_lvalue( T ) ) {@\impl{m_l_scalar}@ 3781 3780 T ?++( T * ), ?( T * );@\use{scalar}@@\use{m_lvalue}@ 3782 3781 T ++?( T * ), ?( T * ); … … 3787 3786 Note that this results in the ``inheritance'' of \lstinline$scalar$ along both paths. 3788 3787 \begin{lstlisting} 3789 context m_l_arithmetic(type T  m_l_scalar( T )  arithmetic( T ) ) {@\impl{m_l_arithmetic}@3788 trait m_l_arithmetic( otype T  m_l_scalar( T )  arithmetic( T ) ) {@\impl{m_l_arithmetic}@ 3790 3789 T ?/=?( T *, T ), ?*=?( T *, T );@\use{m_l_scalar}@@\use{arithmetic}@ 3791 3790 T ?+=?( T *, T ), ?=?( T *, T ); 3792 3791 }; 3793 context m_l_integral(type T  m_l_arithmetic( T )  integral( T ) ) {@\impl{m_l_integral}@3792 trait m_l_integral( otype T  m_l_arithmetic( T )  integral( T ) ) {@\impl{m_l_integral}@ 3794 3793 T ?&=?( T *, T ), ?=?( T *, T ), ?^=?( T *, T );@\use{m_l_arithmetic}@ 3795 3794 T ?%=?( T *, T ), ?<<=?( T *, T ), ?>>=?( T *, T );@\use{integral}@ … … 3811 3810 \lstinline$arithmetic$, so these operators cannot be consolidated in \lstinline$scalar$. 3812 3811 \begin{lstlisting} 3813 context pointer( type P  scalar( P ) ) {@\impl{pointer}@@\use{scalar}@3812 trait pointer( type P  scalar( P ) ) {@\impl{pointer}@@\use{scalar}@ 3814 3813 P ?+?( P, long int ), ?+?( long int, P ), ??( P, long int ); 3815 3814 ptrdiff_t ??( P, P ); 3816 3815 }; 3817 context m_l_pointer( type P  pointer( P )  m_l_scalar( P ) ) {@\impl{m_l_pointer}@3816 trait m_l_pointer( type P  pointer( P )  m_l_scalar( P ) ) {@\impl{m_l_pointer}@ 3818 3817 P ?+=?( P *, long int ), ?=?( P *, long int ); 3819 3818 P ?=?( P *, void * ); … … 3827 3826 ``\lstinline$Safe_pointer$ acts like a pointer to \lstinline$int$''. 3828 3827 \begin{lstlisting} 3829 context ptr_to( type P  pointer( P ),type T ) {@\impl{ptr_to}@@\use{pointer}@3828 trait ptr_to( type P  pointer( P ), otype T ) {@\impl{ptr_to}@@\use{pointer}@ 3830 3829 lvalue T *?( P ); 3831 3830 lvalue T ?[?]( P, long int ); 3832 3831 }; 3833 context ptr_to_const( type P  pointer( P ),type T ) {@\impl{ptr_to_const}@3832 trait ptr_to_const( type P  pointer( P ), otype T ) {@\impl{ptr_to_const}@ 3834 3833 const lvalue T *?( P ); 3835 3834 const lvalue T ?[?]( P, long int );@\use{pointer}@ 3836 3835 }; 3837 context ptr_to_volatile( type P  pointer( P ),type T ) }@\impl{ptr_to_volatile}@3836 trait ptr_to_volatile( type P  pointer( P ), otype T ) }@\impl{ptr_to_volatile}@ 3838 3837 volatile lvalue T *?( P ); 3839 3838 volatile lvalue T ?[?]( P, long int );@\use{pointer}@ 3840 3839 }; 3841 context ptr_to_const_volatile( type P  pointer( P ),type T ) }@\impl{ptr_to_const_volatile}@3840 trait ptr_to_const_volatile( type P  pointer( P ), otype T ) }@\impl{ptr_to_const_volatile}@ 3842 3841 const volatile lvalue T *?( P );@\use{pointer}@ 3843 3842 const volatile lvalue T ?[?]( P, long int ); … … 3849 3848 ``\lstinline$ptr_to$'' specifications. 3850 3849 \begin{lstlisting} 3851 context m_l_ptr_to( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to}@type T  ptr_to( P, T )@\use{ptr_to}@ {3850 trait m_l_ptr_to( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to}@ otype T  ptr_to( P, T )@\use{ptr_to}@ { 3852 3851 P ?=?( P *, T * ); 3853 3852 T * ?=?( T **, P ); 3854 3853 }; 3855 context m_l_ptr_to_const( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_const}@type T  ptr_to_const( P, T )@\use{ptr_to_const}@) {3854 trait m_l_ptr_to_const( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_const}@ otype T  ptr_to_const( P, T )@\use{ptr_to_const}@) { 3856 3855 P ?=?( P *, const T * ); 3857 3856 const T * ?=?( const T **, P ); 3858 3857 }; 3859 context m_l_ptr_to_volatile( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_volatile}@type T  ptr_to_volatile( P, T )) {@\use{ptr_to_volatile}@3858 trait m_l_ptr_to_volatile( type P  m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_volatile}@ otype T  ptr_to_volatile( P, T )) {@\use{ptr_to_volatile}@ 3860 3859 P ?=?( P *, volatile T * ); 3861 3860 volatile T * ?=?( volatile T **, P ); 3862 3861 }; 3863 context m_l_ptr_to_const_volatile( type P  ptr_to_const_volatile( P ),@\use{ptr_to_const_volatile}@@\impl{m_l_ptr_to_const_volatile}@3862 trait m_l_ptr_to_const_volatile( type P  ptr_to_const_volatile( P ),@\use{ptr_to_const_volatile}@@\impl{m_l_ptr_to_const_volatile}@ 3864 3863 type T  m_l_ptr_to_volatile( P, T )  m_l_ptr_to_const( P )) {@\use{m_l_ptr_to_const}@@\use{m_l_ptr_to_volatile}@ 3865 3864 P ?=?( P *, const volatile T * ); … … 3871 3870 An alternative specification can make use of the fact that qualification of the pointedat type is part of a pointer type to capture that regularity. 3872 3871 \begin{lstlisting} 3873 context m_l_ptr_like( type MyP  m_l_pointer( MyP ),@\use{m_l_pointer}@@\impl{m_l_ptr_like}@ type CP  m_l_pointer( CP ) ) {3872 trait m_l_ptr_like( type MyP  m_l_pointer( MyP ),@\use{m_l_pointer}@@\impl{m_l_ptr_like}@ type CP  m_l_pointer( CP ) ) { 3874 3873 MyP ?=?( MyP *, CP ); 3875 3874 CP ?=?( CP *, MyP ); … … 3904 3903 C and \CFA have an extra, nonobvious comparison operator: ``\lstinline$!$'', logical negation, returns 1 if its operand compares equal to 0, and 0 otherwise. 3905 3904 \begin{lstlisting} 3906 context comparable(type T ) {3905 trait comparable( otype T ) { 3907 3906 const T 0; 3908 3907 int compare( T, T ); 3909 3908 } 3910 forall( type T  comparable( T ) ) int ?<?( T l, T r ) {3909 forall( otype T  comparable( T ) ) int ?<?( T l, T r ) { 3911 3910 return compare( l, r ) < 0; 3912 3911 } 3913 3912 // ... similarly for <=, ==, >=, >, and !=. 3914 forall( type T  comparable( T ) ) int !?( T operand ) {3913 forall( otype T  comparable( T ) ) int !?( T operand ) { 3915 3914 return !compare( operand, 0 ); 3916 3915 } … … 3924 3923 Similarly, a complete integral type would provide integral operations based on integral assignment operations. 3925 3924 \begin{lstlisting} 3926 context arith_base(type T ) {3925 trait arith_base( otype T ) { 3927 3926 const T 1; 3928 3927 T ?+=?( T *, T ), ?=?( T *, T ), ?*=?( T *, T ), ?/=?( T *, T ); 3929 3928 } 3930 forall( type T  arith_base( T ) ) T ?+?( T l, T r ) {3929 forall( otype T  arith_base( T ) ) T ?+?( T l, T r ) { 3931 3930 return l += r; 3932 3931 } 3933 forall( type T  arith_base( T ) ) T ?++( T * operand ) {3932 forall( otype T  arith_base( T ) ) T ?++( T * operand ) { 3934 3933 T temporary = *operand; 3935 3934 *operand += 1; 3936 3935 return temporary; 3937 3936 } 3938 forall( type T  arith_base( T ) ) T ++?( T * operand ) {3937 forall( otype T  arith_base( T ) ) T ++?( T * operand ) { 3939 3938 return *operand += 1; 3940 3939 } 3941 3940 // ... similarly for , , *, and /. 3942 context int_base(type T ) {3941 trait int_base( otype T ) { 3943 3942 T ?&=?( T *, T ), ?=?( T *, T ), ?^=?( T *, T ); 3944 3943 T ?%=?( T *, T ), ?<<=?( T *, T ), ?>>=?( T *, T ); 3945 3944 } 3946 forall( type T  int_base( T ) ) T ?&?( T l, T r ) {3945 forall( otype T  int_base( T ) ) T ?&?( T l, T r ) { 3947 3946 return l &= r; 3948 3947 }
Note: See TracChangeset
for help on using the changeset viewer.