# Changeset 10c7f40

Ignore:
Timestamp:
Feb 15, 2021, 10:41:44 AM (8 months ago)
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
e94eeb9
Parents:
52f6250
Message:

formatting, rewrite section of "with" statement

File:
1 edited

### Legend:

Unmodified
 r52f6250 %% Created On       : Wed Apr  6 14:53:29 2016 %% Last Modified By : Peter A. Buhr %% Last Modified On : Mon Feb  8 21:53:31 2021 %% Update Count     : 4327 %% Last Modified On : Mon Feb 15 09:54:33 2021 %% Update Count     : 4442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \author{ \huge \CFA Team \medskip \\ \huge \CFA Team (past and present) \medskip \\ \Large Andrew Beach, Richard Bilson, Michael Brooks, Peter A. Buhr, Thierry Delisle, \smallskip \\ \Large Glen Ditchfield, Rodolfo G. Esteves, Aaron Moss, Colby Parsons, Rob Schluntz, \smallskip \\ \vspace*{\fill} \noindent \copyright\,2016 \CFA Project \\ \\ \copyright\,2016, 2018, 2021 \CFA Project \\ \\ \noindent This work is licensed under the Creative Commons Attribution 4.0 International License. \hline \begin{cfa} while @()@ { sout | "empty"; break; } do { sout | "empty"; break; } while @()@; for @()@ { sout | "empty"; break; } while @($\,$)@ { sout | "empty"; break; } do { sout | "empty"; break; } while @($\,$)@; for @($\,$)@ { sout | "empty"; break; } for ( @0@ ) { sout | "A"; } sout | "zero"; for ( @1@ ) { sout | "A"; } \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} While C provides ©continue© and ©break© statements for altering control flow, both are restricted to one level of nesting for a particular control structure. Unfortunately, this restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting. C ©continue© and ©break© statements, for altering control flow, are restricted to one level of nesting for a particular control structure. This restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting. To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java. For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement; for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement. \VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels. \VRef[Figure]{f:MultiLevelExit} shows a comparison between labelled ©continue© and ©break© and the corresponding C equivalent using ©goto© and labels. The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s. \end{lrbox} \hspace*{-10pt} \subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA} \hspace{2pt} \hspace{3pt} \vrule \hspace{3pt} \subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB} \caption{Multi-level Exit} This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in undefined behaviour. \end{itemize} The advantage of the labelled ©continue©/©break© is allowing static multi-level exits without having to use the ©goto© statement, and tying control flow to the target control structure rather than an arbitrary point in a program. The advantage of the labelled ©continue©/©break© is allowing static multi-level exits without having to use the ©goto© statement, and tying control flow to the target control structure rather than an arbitrary point in a program via a label. Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader (\Index{eye candy}) that complex control-flow is occurring in the body of the control structure. With ©goto©, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader. %\section{\texorpdfstring{\protect\lstinline@with@ Statement}{with Statement}} \section{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}} %\subsection{\texorpdfstring{\protect\lstinline@with@ Statement}{with Statement}} \subsection{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}} \label{s:WithStatement} Grouping heterogeneous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers: \begin{cfa} struct S { $\C{// aggregate}$ char c; $\C{// fields}$ int i; double d; Grouping heterogeneous data into an \newterm{aggregate} (structure/union) is a common programming practice, and aggregates may be nested: \begin{cfa} struct Person {                                                         $\C{// aggregate}$ struct Name {                                                   $\C{// nesting}$ char first[20], last[20]; } name; struct Address {                                                $\C{// nesting}$ ... } address; int sex; }; S s, as[10]; \end{cfa} However, functions manipulating aggregates must repeat the aggregate name to access its containing fields: \begin{cfa} void f( S s ) { @s.@c; @s.@i; @s.@d; $\C{// access containing fields}$ } \end{cfa} which extends to multiple levels of qualification for nested aggregates. A similar situation occurs in object-oriented programming, \eg \CC: \end{cfa} Functions manipulating aggregates must repeat the aggregate name to access its containing fields. \begin{cfa} Person p @p.@name; @p.@address; @p.@sex; $\C{// access containing fields}$ \end{cfa} which extends to multiple levels of qualification for nested aggregates and multiple aggregates. \begin{cfa} struct Ticket { ... } t; @p.name@.first; @p.address@.street;             $\C{// access nested fields}$ @t.@departure; @t.@cost;                                $\C{// access multiple aggregate}$ \end{cfa} Repeated aggregate qualification is tedious and makes code difficult to read. Therefore, reducing aggregate qualification is a useful language design goal. C allows unnamed nested aggregates that open their scope into the containing aggregate. However, this feature is only useful for ©union© aggregates. \begin{cfa} struct S { union { char @c@;   int @i@;   double @d@; }; int tag; } s; @s@.tag; @s@.c; @s@.i; @s@.d;                           $\C{// no nested qualification for union fields}$ \end{cfa} Object-oriented languages reduce qualification for class variables within member functions, \eg \CC: \begin{C++} struct S { char c; $\C{// fields}$ int i; double d; void f() { $\C{// implicit this'' aggregate}$ @this->@c; @this->@i; @this->@d; $\C{// access containing fields}$ char @c@;   int @i@;   double @d@; void f( /* S * this */ ) {                              $\C{// implicit this'' parameter}$ @c@;   @i@;   @d@;                                      $\C{// this->c; this->i; this->d;}$ } } \end{C++} Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping. However, for other aggregate parameters, qualification is necessary: \begin{cfa} struct T { double m, n; }; int S::f( T & t ) { $\C{// multiple aggregate parameters}$ c; i; d; $\C{\R{// this--{\textgreater}c, this--{\textgreater}i, this--{\textgreater}d}}$ @t.@m; @t.@n; $\C{// must qualify}$ } \end{cfa} To simplify the programmer experience, \CFA provides a ©with© statement \see{Pascal~\cite[\S~4.F]{Pascal}} to elide aggregate qualification to fields by opening a scope containing the field identifiers. Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block. \begin{cfa} void f( S & this ) @with ( this )@ { $\C{// with statement}$ c; i; d; $\C{\R{// this.c, this.i, this.d}}$ In general, qualification is elided for the variables and functions in the lexical scopes visible from a member function. However, qualification is necessary for name shadowing and explicit aggregate parameters. \begin{cfa} struct T { char @m@;   int @i@;   double @n@;              $\C{// derived class variables}$ }; struct S : public T { char @c@;   int @i@;   double @d@;              $\C{// class variables}$ void g( double @d@, T & t ) { d;   @t@.m;   @t@.i;   @t@.n;           $\C{// function parameter}$ c;   i;   @this->@d;   @S::@d;          $\C{// class S variables}$ m;   @T::@i;   n;                                       $\C{// class T variables}$ } }; \end{cfa} Note the three different forms of qualification syntax in \CC, ©.©, ©->©, ©::©, which is confusing. Since \CFA in not object-oriented, it has no implicit parameter with its implicit qualification. Instead \CFA introduces a general mechanism using the ©with© statement \see{Pascal~\cite[\S~4.F]{Pascal}} to explicitly elide aggregate qualification by opening a scope containing the field identifiers. Hence, the qualified fields become variables with the side-effect that it is simpler to write, easier to read, and optimize field references in a block. \begin{cfa} void f( S & this ) @with ( this )@ {            $\C{// with statement}$ @c@;   @i@;   @d@;                                              $\C{// this.c, this.i, this.d}$ } \end{cfa} with the generality of opening multiple aggregate-parameters: \begin{cfa} void f( S & s, T & t ) @with ( s, t )@ { $\C{// multiple aggregate parameters}$ c; i; d; $\C{\R{// s.c, s.i, s.d}}$ m; n; $\C{\R{// t.m, t.n}}$ } \end{cfa} In detail, the ©with© statement has the form: \begin{cfa} $\emph{with-statement}$: 'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$ \end{cfa} and may appear as the body of a function or nested within a function body. Each expression in the expression-list provides a type and object. The type must be an aggregate type. void g( S & s, T & t ) @with ( s, t )@ {        $\C{// multiple aggregate parameters}$ c;   @s.@i;   d;                                                $\C{// s.c, s.i, s.d}$ m;   @t.@i;   n;                                                $\C{// t.m, t.i, t.n}$ } \end{cfa} where qualification is only necessary to disambiguate the shadowed variable ©i©. In detail, the ©with© statement may appear as the body of a function or nested within a function body. The ©with© clause takes a list of expressions, where each expression provides an aggregate type and object. (Enumerations are already opened.) The object is the implicit qualifier for the open structure-fields. To open a pointer type, the pointer must be dereferenced to obtain a reference to the aggregate type. \begin{cfa} S * sp; with ( *sp ) { ... } \end{cfa} The expression object is the implicit qualifier for the open structure-fields. \CFA's ability to overload variables \see{\VRef{s:VariableOverload}} and use the left-side of assignment in type resolution means most fields with the same name but different types are automatically disambiguated, eliminating qualification. All expressions in the expression list are open in parallel within the compound statement. This semantic is different from Pascal, which nests the openings from left to right. The difference between parallel and nesting occurs for fields with the same name and type: \begin{cfa} struct S { int @i@; int j; double m; } s, w; struct T { int @i@; int k; int m; } t, w; with ( s, t ) { j + k; $\C{// unambiguous, s.j + t.k}$ m = 5.0; $\C{// unambiguous, t.m = 5.0}$ m = 1; $\C{// unambiguous, s.m = 1}$ int a = m; $\C{// unambiguous, a = s.i }$ double b = m; $\C{// unambiguous, b = t.m}$ int c = s.i + t.i; $\C{// unambiguous, qualification}$ (double)m; $\C{// unambiguous, cast}$ } \end{cfa} For parallel semantics, both ©s.i© and ©t.i© are visible, so ©i© is ambiguous without qualification; for nested semantics, ©t.i© hides ©s.i©, so ©i© implies ©t.i©. \CFA's ability to overload variables means fields with the same name but different types are automatically disambiguated, eliminating most qualification when opening multiple aggregates. Qualification or a cast is used to disambiguate. There is an interesting problem between parameters and the function-body ©with©, \eg: struct Q { int @i@; int k; int @m@; } q, w; struct R { int @i@; int j; double @m@; } r, w; with ( r, q ) { j + k;                                                                  $\C{// unambiguous, r.j + q.k}$ m = 5.0;                                                                $\C{// unambiguous, q.m = 5.0}$ m = 1;                                                                  $\C{// unambiguous, r.m = 1}$ int a = m;                                                              $\C{// unambiguous, a = r.i }$ double b = m;                                                   $\C{// unambiguous, b = q.m}$ int c = r.i + q.i;                                              $\C{// disambiguate with qualification}$ (double)m;                                                              $\C{// disambiguate with cast}$ } \end{cfa} For parallel semantics, both ©r.i© and ©q.i© are visible, so ©i© is ambiguous without qualification; for nested semantics, ©q.i© hides ©r.i©, so ©i© implies ©q.i©. Pascal nested-semantics is possible by nesting ©with© statements. \begin{cfa} with ( r ) { i;                                                                              $\C{// unambiguous, r.i}$ with ( q ) { i;                                                                      $\C{// unambiguous, q.i}$ } } \end{cfa} A cast or qualification can be used to disambiguate variables within a ©with© \emph{statement}. A cast can be used to disambiguate among overload variables in a ©with© \emph{expression}: \begin{cfa} with ( w ) { ... }                                                      $\C{// ambiguous, same name and no context}$ with ( (Q)w ) { ... }                                           $\C{// unambiguous, cast}$ \end{cfa} Because there is no left-side in the ©with© expression to implicitly disambiguate between the ©w© variables, it is necessary to explicitly disambiguate by casting ©w© to type ©Q© or ©R©. Finally, there is an interesting problem between parameters and the function-body ©with©, \eg: \begin{cfa} void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ and implicitly opened \emph{after} a function-body open, to give them higher priority: \begin{cfa} void ?{}( S & s, int @i@ ) with ( s ) @with( $\emph{\R{params}}$ )@ { void ?{}( S & s, int @i@ ) with ( s ) @with( $\emph{\R{params}}$ )@ { // syntax not allowed, illustration only s.i = @i@; j = 3; m = 5.5; } \end{cfa} Finally, a cast may be used to disambiguate among overload variables in a ©with© expression: \begin{cfa} with ( w ) { ... } $\C{// ambiguous, same name and no context}$ with ( (S)w ) { ... } $\C{// unambiguous, cast}$ \end{cfa} and ©with© expressions may be complex expressions with type reference \see{\VRef{s:References}} to aggregate: % \begin{cfa} % struct S { int i, j; } sv; % with ( sv ) { $\C{// implicit reference}$ %       S & sr = sv; %       with ( sr ) { $\C{// explicit reference}$ %               S * sp = &sv; %               with ( *sp ) { $\C{// computed reference}$ %                       i = 3; j = 4; $\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}$ %               } %               i = 2; j = 3; $\C{\color{red}// sr.i, sr.j}$ %       } %       i = 1; j = 2; $\C{\color{red}// sv.i, sv.j}$ % } % \end{cfa} In \Index{object-oriented} programming, there is an implicit first parameter, often names \textbf{©self©} or \textbf{©this©}, which is elided. \begin{C++} class C { int i, j; int mem() { $\C{\R{// implicit "this" parameter}}$ i = 1; $\C{\R{// this->i}}$ j = 2; $\C{\R{// this->j}}$ } } \end{C++} Since \CFA is non-object-oriented, the equivalent object-oriented program looks like: \begin{cfa} struct S { int i, j; }; int mem( S & @this@ ) { $\C{// explicit "this" parameter}$ @this.@i = 1; $\C{// "this" is not elided}$ @this.@j = 2; } \end{cfa} but it is cumbersome having to write ©this.©'' many times in a member. \CFA provides a ©with© clause/statement \see{Pascal~\cite[\S~4.F]{Pascal}} to elided the "©this.©" by opening a scope containing field identifiers, changing the qualified fields into variables and giving an opportunity for optimizing qualified references. \begin{cfa} int mem( S & this ) @with( this )@ { $\C{// with clause}$ i = 1; $\C{\R{// this.i}}$ j = 2; $\C{\R{// this.j}}$ } \end{cfa} which extends to multiple routine parameters: \begin{cfa} struct T { double m, n; }; int mem2( S & this1, T & this2 ) @with( this1, this2 )@ { i = 1; j = 2; m = 1.0; n = 2.0; } \end{cfa} The statement form is used within a block: \begin{cfa} int foo() { struct S1 { ... } s1; struct S2 { ... } s2; @with( s1 )@ { $\C{// with statement}$ // access fields of s1 without qualification @with s2@ { $\C{// nesting}$ // access fields of s1 and s2 without qualification } } @with s1, s2@ { // access unambiguous fields of s1 and s2 without qualification } } \end{cfa} When opening multiple structures, fields with the same name and type are ambiguous and must be fully qualified. For fields with the same name but different type, context/cast can be used to disambiguate. \begin{cfa} struct S { int i; int j; double m; } a, c; struct T { int i; int k; int m } b, c; with( a, b ) { } \end{cfa} \begin{comment} The components in the "with" clause with a, b, c { ... } serve 2 purposes: each component provides a type and object. The type must be a structure type. Enumerations are already opened, and I think a union is opened to some extent, too. (Or is that just unnamed unions?) The object is the target that the naked structure-fields apply to. The components are open in "parallel" at the scope of the "with" clause/statement, so opening "a" does not affect opening "b", etc. This semantic is different from Pascal, which nests the openings. Having said the above, it seems reasonable to allow a "with" component to be an expression. The type is the static expression-type and the object is the result of the expression. Again, the type must be an aggregate. Expressions require parenthesis around the components. with( a, b, c ) { ... } Does this now make sense? Having written more CFA code, it is becoming clear to me that I *really* want the "with" to be implemented because I hate having to type all those object names for fields. It's a great way to drive people away from the language. \end{comment} This implicit semantic matches with programmer expectation. \subsection{Overloaded Constant} \subsection{Constant} The constants 0 and 1 have special meaning. \subsection{Variable Overloading} \subsection{Variable} \label{s:VariableOverload} The overload rules of \CFA allow a programmer to define multiple variables with the same name, but different types. \subsection{Operator Overloading} \subsection{Operator} \CFA also allows operators to be overloaded, to simplify the use of user-defined types. \end{cfa} & \begin{lstlisting}[language=C++] \begin{C++} class Line { float lnth; Line line1; Line line2( 3.4 ); \end{lstlisting} \end{C++} & \begin{lstlisting}[language=Golang]