Changeset cbe477e
- Timestamp:
- Feb 5, 2018, 4:55:35 PM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 43bbdf3, 7ad6b6d
- Parents:
- 51b5a02
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/papers/general/Paper.tex
r51b5a02 rcbe477e 1038 1038 The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed. 1039 1039 1040 \TODO{choose and fallthrough here as well?} 1040 1041 1041 1042 \subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}} … … 1162 1163 \subsection{References} 1163 1164 1164 \TODO{Pull draft text from user manual; make sure to discuss nested references and rebind operator drawn from lvalue-addressof operator} 1165 1165 All variables in C have an \emph{address}, a \emph{value}, and a \emph{type}; at the position in the program's memory denoted by the address, there exists a sequence of bits (the value), with the length and semantic meaning of this bit sequence defined by the type. 1166 The C type system does not always track the relationship between a value and its address; a value that does not have a corresponding address is called a \emph{rvalue} (for ``right-hand value''), while a value that does have an address is called a \emph{lvalue} (for ``left-hand value''); in @int x; x = 42;@ the variable expression @x@ on the left-hand-side of the assignment is a lvalue, while the constant expression @42@ on the right-hand-side of the assignment is a rvalue. 1167 Which address a value is located at is sometimes significant; the imperative programming paradigm of C relies on the mutation of values at specific addresses. 1168 Within a lexical scope, lvalue exressions can be used in either their \emph{address interpretation} to determine where a mutated value should be stored or in their \emph{value interpretation} to refer to their stored value; in @x = y;@ in @{ int x, y = 7; x = y; }@, @x@ is used in its address interpretation, while y is used in its value interpretation. 1169 Though this duality of interpretation is useful, C lacks a direct mechanism to pass lvalues between contexts, instead relying on \emph{pointer types} to serve a similar purpose. 1170 In C, for any type @T@ there is a pointer type @T*@, the value of which is the address of a value of type @T@; a pointer rvalue can be explicitly \emph{dereferenced} to the pointed-to lvalue with the dereference operator @*?@, while the rvalue representing the address of a lvalue can be obtained with the address-of operator @&?@. 1171 1172 \begin{cfa} 1173 int x = 1, y = 2, * p1, * p2, ** p3; 1174 p1 = &x; $\C{// p1 points to x}$ 1175 p2 = &y; $\C{// p2 points to y}$ 1176 p3 = &p1; $\C{// p3 points to p1}$ 1177 \end{cfa} 1178 1179 Unfortunately, the dereference and address-of operators introduce a great deal of syntactic noise when dealing with pointed-to values rather than pointers, as well as the potential for subtle bugs. 1180 It would be desirable to have the compiler figure out how to elide the dereference operators in a complex expression such as @*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);@, for both brevity and clarity. 1181 However, since C defines a number of forms of \emph{pointer arithmetic}, two similar expressions involving pointers to arithmetic types (\eg @*p1 + x@ and @p1 + x@) may each have well-defined but distinct semantics, introducing the possibility that a user programmer may write one when they mean the other, and precluding any simple algorithm for elision of dereference operators. 1182 To solve these problems, \CFA introduces reference types @T&@; a @T&@ has exactly the same value as a @T*@, but where the @T*@ takes the address interpretation by default, a @T&@ takes the value interpretation by default, as below: 1183 1184 \begin{cfa} 1185 inx x = 1, y = 2, & r1, & r2, && r3; 1186 &r1 = &x; $\C{// r1 points to x}$ 1187 &r2 = &y; $\C{// r2 points to y}$ 1188 &&r3 = &&r1; $\C{// r3 points to r2}$ 1189 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); $\C{// implicit dereferencing}$ 1190 \end{cfa} 1191 1192 Except for auto-dereferencing by the compiler, this reference example is exactly the same as the previous pointer example. 1193 Hence, a reference behaves like a variable name -- an lvalue expression which is interpreted as a value, but also has the type system track the address of that value. 1194 One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in the reference variable declaration, so the previous example implicitly acts like: 1195 1196 \begin{cfa} 1197 `*`r2 = ((`*`r1 + `*`r2) * (`**`r3 - `*`r1)) / (`**`r3 - 15); 1198 \end{cfa} 1199 1200 References in \CFA are similar to those in \CC, but with a couple important improvements, both of which can be seen in the example above. 1201 Firstly, \CFA does not forbid references to references, unlike \CC. 1202 This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@. 1203 1204 Secondly, unlike the references in \CC which always point to a fixed address, \CFA references are rebindable. 1205 This allows \CFA references to be default-initialized (to a null pointer), and also to point to different addresses throughout their lifetime. 1206 This rebinding is accomplished without adding any new syntax to \CFA, but simply by extending the existing semantics of the address-of operator in C. 1207 In C, the address of a lvalue is always a rvalue, as in general that address is not stored anywhere in memory, and does not itself have an address. 1208 In \CFA, the address of a @T&@ is a lvalue @T*@, as the address of the underlying @T@ is stored in the reference, and can thus be mutated there. 1209 The result of this rule is that any reference can be rebound using the existing pointer assignment semantics by assigning a compatible pointer into the address of the reference, \eg @&r1 = &x;@ above. 1210 This rebinding can occur to an arbitrary depth of reference nesting; $n$ address-of operators applied to a reference nested $m$ times will produce an lvalue pointer nested $n$ times if $n \le m$ (note that $n = m+1$ is simply the usual C rvalue address-of operator applied to the $n = m$ case). 1211 The explicit address-of operators can be thought of as ``cancelling out'' the implicit dereference operators, \eg @(&`*`)r1 = &x;@ or @(&(&`*`)`*`)r3 = &(&`*`)r1;@ or even @(&`*`)r2 = (&`*`)`*`r3;@ for @&r2 = &r3;@. 1212 1213 Since pointers and references share the same internal representation, code using either is equally performant; in fact the \CFA compiler converts references to pointers internally, and the choice between them in user code can be made based solely on convenience. 1214 By analogy to pointers, \CFA references also allow cv-qualifiers: 1215 1216 \begin{cfa} 1217 const int cx = 5; $\C{// cannot change cx}$ 1218 const int & cr = cx; $\C{// cannot change cr's referred value}$ 1219 &cr = &cx; $\C{// rebinding cr allowed}$ 1220 cr = 7; $\C{// ERROR, cannot change cr}$ 1221 int & const rc = x; $\C{// must be initialized, like in \CC}$ 1222 &rc = &x; $\C{// ERROR, cannot rebind rc}$ 1223 rc = 7; $\C{// x now equal to 7}$ 1224 \end{cfa} 1225 1226 \TODO{Pull more draft text from user manual; make sure to discuss initialization and reference conversions} 1166 1227 1167 1228 \subsection{Constructors and Destructors} … … 1182 1243 \subsection{0/1} 1183 1244 1245 \TODO{Some text already at the end of Section~\ref{sec:poly-fns}} 1184 1246 1185 1247 \subsection{Units}
Note: See TracChangeset
for help on using the changeset viewer.