Index: doc/rob_thesis/conclusions.tex
===================================================================
--- doc/rob_thesis/conclusions.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/conclusions.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -2,4 +2,9 @@
 \chapter{Conclusions}
 %======================================================================
+
+Adding resource management and tuples to \CFA has been a challenging design, engineering, and implementation exercise.
+On the surface, the work may appear as a rehash of similar mechanisms in \CC.
+However, every added feature is different than its \CC counterpart, often with extended functionality, better integration with C and its programmers, and always supports separate compilation.
+All of these new features are being used by the \CFA development-team to build the \CFA runtime system.
 
 \section{Constructors and Destructors}
@@ -18,5 +23,5 @@
 
 \section{Variadic Functions}
-Type-safe variadic functions of a similar feel to variadic templates are added to \CFA.
+Type-safe variadic functions, with a similar feel to variadic templates, are added to \CFA.
 The new variadic functions can express complicated recursive algorithms.
 Unlike variadic templates, it is possible to write @new@ as a library routine and to separately compile @ttype@ polymorphic functions.
@@ -29,4 +34,18 @@
 The design space is currently being explored with the goal of finding an alternative to move semantics that provides necessary performance benefits, while reducing the amount of repetition required to create a new type, along with the cognitive burden placed on the user.
 
+% One technique being evaluated is whether named return-values can be used to eliminate unnecessary temporaries \cite{Buhr94a}.
+% For example,
+% \begin{cfacode}
+% struct A { ... };
+% [A x] f(A x);
+% [A y] g(A y);
+% [A z] h(A z);
+
+% struct A a1, a2;
+% a2 = h(g(f(a1)));
+% \end{cfacode}
+% Here, since both @f@'s argument and return value have the same name and type, the compiler can infer that @f@ returns its argument.
+% With this knowledge, the compiler can reuse the storage for the argument to @f@ as the argument to @g@.  % TODO: cite Till thesis?
+
 Exception handling is among the features expected to be added to \CFA in the near future.
 For exception handling to properly interact with the rest of the language, it must ensure all RAII guarantees continue to be met.
@@ -44,6 +63,6 @@
 This mechanism is known and understood by GCC, so that the destructor is properly called in any situation where a variable goes out of scope, including function returns, branches, and built-in GCC exception handling mechanisms using libunwind.
 
-A caveat of this approach is that the @cleanup@ attribute only permits a name that refers to a function that consumes a single argument of type @T *@ for a variable of type @T@.
-This means that any destructor that consumes multiple arguments (\eg, because it is polymorphic) or any destructor that is a function pointer (\eg, because it is an assertion parameter) must be called through a local thunk.
+A caveat of this approach is that the @cleanup@ attribute only permits a function that consumes a single argument of type @T *@ for a variable of type @T@.
+This restriction means that any destructor that consumes multiple arguments (\eg, because it is polymorphic) or any destructor that is a function pointer (\eg, because it is an assertion parameter) must be called through a local thunk.
 For example,
 \begin{cfacode}
@@ -52,10 +71,10 @@
   T x;
 };
-forall(otype T) void ^?{}(Box(T) * x);
+forall(otype T) void ^?{}(Box(T) * x); // has implicit parameters
 
 forall(otype T)
 void f(T x) {
-  T y = x;
-  Box(T) z = { x };
+  T y = x;  // destructor is a function-pointer parameter
+  Box(T) z = { x }; // destructor has multiple parameters
 }
 \end{cfacode}
@@ -148,10 +167,10 @@
 void _dtor_S(struct S *);
 
-struct __tmp_bundle_S {
+struct _tmp_bundle_S {
   bool valid;
   struct S value;
 };
 
-void _dtor_tmpS(struct __tmp_bundle_S * ret) {
+void _dtor_tmpS(struct _tmp_bundle_S * ret) {
   if (ret->valid) {
     _dtor_S(&ret->value);
@@ -160,7 +179,7 @@
 
 {
-  __attribute__((cleanup(_dtor_tmpS))) struct __tmp_bundle_S _tmp1 = { 0 };
-  __attribute__((cleanup(_dtor_tmpS))) struct __tmp_bundle_S _tmp2 = { 0 };
-  __attribute__((cleanup(_dtor_tmpS))) struct __tmp_bundle_S _tmp3 = { 0 };
+  __attribute__((cleanup(_dtor_tmpS))) struct _tmp_bundle_S _tmp1 = { 0 };
+  __attribute__((cleanup(_dtor_tmpS))) struct _tmp_bundle_S _tmp2 = { 0 };
+  __attribute__((cleanup(_dtor_tmpS))) struct _tmp_bundle_S _tmp3 = { 0 };
   _tmp2.value = g(
     (_ctor_S(
@@ -189,5 +208,5 @@
 struct S { T x; };
 \end{cfacode}
-will only auto-generate the default constructor for @S@, since the member @x@ is missing the other 3 special functions.
+only auto-generates the default constructor for @S@, since the member @x@ is missing the other 3 special functions.
 Once deleted functions have been added, function generation can make use of this information to disable generation of special functions when a member has a deleted function.
 For example,
@@ -210,19 +229,19 @@
 struct B { ... };
 struct A {
-	B x, y, z;
+  B x, y, z;
 };
 void ?{}(A * a, B x) {
-	// y, z implicitly default constructed
-	(&a->x){ ... }; // explicitly construct x
+  // y, z implicitly default constructed
+  (&a->x){ ... }; // explicitly construct x
 } // constructs an entire A
 void ?{}(A * a) {
-	(&a->y){}; // initialize y
-	a{ (B){ ... } }; // forwarding constructor call
-	                 // initializes entire object, including y
+  (&a->y){}; // initialize y
+  a{ (B){ ... } }; // forwarding constructor call
+                   // initializes entire object, including y
 }
 \end{cfacode}
 
 Finally, while constructors provide a mechanism for establishing invariants, there is currently no mechanism for maintaining invariants without resorting to opaque types.
-That is, structure fields can be accessed and modified by any block of code without restriction, so while it's possible to ensure that an object is initially set to a valid state, it isn't possible to ensure that it remains in a consistent state throughout its lifetime.
+That is, structure fields can be accessed and modified by any block of code without restriction, so while it is possible to ensure that an object is initially set to a valid state, it is not possible to ensure that it remains in a consistent state throughout its lifetime.
 A popular technique for ensuring consistency in object-oriented programming languages is to provide access modifiers such as @private@, which provides compile-time checks that only privileged code accesses private data.
 This approach could be added to \CFA, but it requires an idiomatic way of specifying what code is privileged.
@@ -239,7 +258,7 @@
 \subsection{Variadic Functions}
 Use of @ttype@ functions currently relies heavily on recursion.
-\CC has opened variadic templates up so that recursion isn't strictly necessary in some cases, and it would be interesting to see if any such cases can be applied to \CFA.
-
-\CC supports variadic templated data types, making it possible to express arbitrary length tuples, arbitrary parameter function objects, and more with generic types.
-Currently, \CFA does not support @ttype@-parameter generic types, though there does not appear to be a technical reason that it cannot.
+\CC has opened variadic templates up so that recursion is not strictly necessary in some cases, and it would be interesting to see if any such cases can be applied to \CFA.
+
+\CC supports variadic templated data-types, making it possible to express arbitrary length tuples, arbitrary parameter function objects, and more with generic types.
+Currently, \CFA does not support @ttype@-parameter generic-types, though there does not appear to be a technical reason that it cannot.
 Notably, opening up support for this makes it possible to implement the exit form of scope guard (see section \ref{s:ResMgmt}), making it possible to call arbitrary functions at scope exit in idiomatic \CFA.
Index: doc/rob_thesis/ctordtor.tex
===================================================================
--- doc/rob_thesis/ctordtor.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/ctordtor.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -291,5 +291,8 @@
 struct X *_tmp_ctor;
 struct X *x = ?{}(  // construct result of malloc
-  _tmp_ctor=malloc_T(sizeof(struct X), _Alignof(struct X)), // store result of malloc
+  _tmp_ctor=malloc_T( // store result of malloc
+    sizeof(struct X),
+    _Alignof(struct X)
+  ),
   1.5
 ), _tmp_ctor; // produce constructed result of malloc
@@ -500,5 +503,5 @@
   S s0, s1 = { 0 }, s2 = { 0, 2 }, s3 = s2;  // okay
   {
-    void ?{}(S * s, int i) { s->x = i*2; } // locally hide autogen constructors
+    void ?{}(S * s, int i) { s->x = i*2; } // locally hide autogen ctors
     S s4;  // error, no default constructor
     S s5 = { 3 };  // okay, local constructor
@@ -577,4 +580,5 @@
 As a result, it was decided that any attempt to resolve designated function calls with C's function prototype rules would be brittle, and thus it is not sensible to allow designations in constructor calls.
 
+\begin{sloppypar}
 In addition, constructor calls do not support unnamed nesting.
 \begin{cfacode}
@@ -594,4 +598,5 @@
 That is, in the previous example the line marked as an error could mean construct using @?{}(A *, B)@ or with @?{}(A *, C)@, since the inner initializer @{ 10 }@ could be taken as an intermediate object of type @B@ or @C@.
 In practice, however, there could be many objects that can be constructed from a given @int@ (or, indeed, any arbitrary parameter list), and thus a complete solution to this problem would require fully exploring all possibilities.
+\end{sloppypar}
 
 More precisely, constructor calls cannot have a nesting depth greater than the number of array dimensions in the type of the initialized object, plus one.
@@ -877,7 +882,7 @@
 This means that in general, function signatures would have to be rewritten, and in a select few cases the signatures would not be rewritten.
 \begin{cfacode}
-__attribute__((manageable)) struct A { ... };   // can declare constructors
-__attribute__((unmanageable)) struct B { ... }; // cannot declare constructors
-struct C { ... };                               // can declare constructors
+__attribute__((manageable)) struct A { ... };   // can declare ctors
+__attribute__((unmanageable)) struct B { ... }; // cannot declare ctors
+struct C { ... };                               // can declare ctors
 
 A f();  // rewritten void f(A *);
@@ -889,6 +894,6 @@
 Furthermore, no restrictions would need to be placed on whether objects can be constructed.
 \begin{cfacode}
-__attribute__((identifiable)) struct A { ... };  // can declare constructors
-struct B { ... };                                // can declare constructors
+__attribute__((identifiable)) struct A { ... };  // can declare ctors
+struct B { ... };                                // can declare ctors
 
 A f();  // rewritten void f(A *);
Index: doc/rob_thesis/intro.tex
===================================================================
--- doc/rob_thesis/intro.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/intro.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -326,8 +326,10 @@
 Invariants help a programmer to reason about code correctness and prove properties of programs.
 
+\begin{sloppypar}
 In object-oriented programming languages, type invariants are typically established in a constructor and maintained throughout the object's lifetime.
 These assertions are typically achieved through a combination of access-control modifiers and a restricted interface.
 Typically, data which requires the maintenance of an invariant is hidden from external sources using the \emph{private} modifier, which restricts reads and writes to a select set of trusted routines, including member functions.
 It is these trusted routines that perform all modifications to internal data in a way that is consistent with the invariant, by ensuring that the invariant holds true at the end of the routine call.
+\end{sloppypar}
 
 In C, the @assert@ macro is often used to ensure invariants are true.
@@ -617,6 +619,6 @@
 Tuples support named access and subscript access, among a few other operations.
 \begin{scalacode}
-val a = new Tuple3[Int, String, Double](0, "Text", 2.1)  // explicit creation
-val b = (6, 'a', 1.1f)       // syntactic sugar for Tuple3[Int, Char, Float]
+val a = new Tuple3(0, "Text", 2.1) // explicit creation
+val b = (6, 'a', 1.1f)       // syntactic sugar: Tuple3[Int, Char, Float]
 val (i, _, d) = triple       // extractor syntax, ignore middle element
 
@@ -661,4 +663,5 @@
 Still, @printf@ is extremely limited, since the format codes are specified by the C standard, meaning users cannot define their own format codes to extend @printf@ for new data types or new formatting rules.
 
+\begin{sloppypar}
 C provides manipulation of variadic arguments through the @va_list@ data type, which abstracts details of the manipulation of variadic arguments.
 Since the variadic arguments are untyped, it is up to the function to interpret any data that is passed in.
@@ -695,4 +698,5 @@
 Furthermore, if the user makes a mistake, compile-time checking is typically restricted to standard format codes and their corresponding types.
 In general, this means that C's variadic functions are not type-safe, making them difficult to use properly.
+\end{sloppypar}
 
 % When arguments are passed to a variadic function, they undergo \emph{default argument promotions}.
Index: doc/rob_thesis/thesis-frontpgs.tex
===================================================================
--- doc/rob_thesis/thesis-frontpgs.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/thesis-frontpgs.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -24,5 +24,5 @@
 
         \Large
-        Rob Schluntz \\
+        Robert Schluntz \\
 
         \vspace*{3.0cm}
@@ -43,5 +43,5 @@
         \vspace*{1.0cm}
 
-        \copyright\ Rob Schluntz 2017 \\
+        \copyright\ Robert Schluntz 2017 \\
         \end{center}
 \end{titlepage}
@@ -77,29 +77,32 @@
 
 \CFA is a modern, non-object-oriented extension of the C programming language.
-This thesis introduces two fundamental language features: tuples and constructors/destructors, as well as improved variadic functions.
+This thesis addresses several critical deficiencies of C, notably: resource management, a limited function-return mechanism, and unsafe variadic functions.
+To solve these problems, two fundamental language features are introduced: tuples and constructors/destructors.
 While these features exist in prior programming languages, the contribution of this work is engineering these features into a highly complex type system.
+C is an established language with a dedicated user-base.
+An important goal is to add new features in a way that naturally feels like C, to appeal to this core user-base, and due to huge amounts of legacy code, maintaining backwards compatibility is crucial.
 
 \cleardoublepage
 %\newpage
 
-% A C K N O W L E D G E M E N T S
-% -------------------------------
+% % A C K N O W L E D G E M E N T S
+% % -------------------------------
 
-\begin{center}\textbf{Acknowledgements}\end{center}
+% \begin{center}\textbf{Acknowledgements}\end{center}
 
-% I would like to thank all the little people who made this possible.
-TODO
-\cleardoublepage
-%\newpage
+% % I would like to thank all the little people who made this possible.
+% TODO
+% \cleardoublepage
+% %\newpage
 
-% D E D I C A T I O N
-% -------------------
+% % D E D I C A T I O N
+% % -------------------
 
-\begin{center}\textbf{Dedication}\end{center}
+% \begin{center}\textbf{Dedication}\end{center}
 
-% This is dedicated to the one I love.
-TODO
-\cleardoublepage
-%\newpage
+% % This is dedicated to the one I love.
+% TODO
+% \cleardoublepage
+% %\newpage
 
 % T A B L E   O F   C O N T E N T S
@@ -119,11 +122,11 @@
 %\newpage
 
-% L I S T   O F   F I G U R E S
-% -----------------------------
-\addcontentsline{toc}{chapter}{List of Figures}
-\listoffigures
-\cleardoublepage
-\phantomsection		% allows hyperref to link to the correct page
-%\newpage
+% % L I S T   O F   F I G U R E S
+% % -----------------------------
+% \addcontentsline{toc}{chapter}{List of Figures}
+% \listoffigures
+% \cleardoublepage
+% \phantomsection		% allows hyperref to link to the correct page
+% %\newpage
 
 % L I S T   O F   S Y M B O L S
Index: doc/rob_thesis/thesis.tex
===================================================================
--- doc/rob_thesis/thesis.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/thesis.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -136,5 +136,5 @@
     pdffitwindow=false,     % window fit to page when opened
     pdfstartview={FitH},    % fits the width of the page to the window
-    pdftitle={uWaterloo\ LaTeX\ Thesis\ Template},    % title: CHANGE THIS TEXT!
+    pdftitle={Resource Management and Tuples in \CFA},    % title: CHANGE THIS TEXT!
     pdfauthor={Rob Schluntz},    % author: CHANGE THIS TEXT! and uncomment this line
 %    pdfsubject={Subject},  % subject: CHANGE THIS TEXT! and uncomment this line
Index: doc/rob_thesis/tuples.tex
===================================================================
--- doc/rob_thesis/tuples.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/tuples.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -209,5 +209,5 @@
 In the call to @f@, @x@ is implicitly flattened so that the components of @x@ are passed as the two arguments to @f@.
 For the call to @g@, the values @y@ and @10@ are structured into a single argument of type @[int, int]@ to match the type of the parameter of @g@.
-Finally, in the call to @h@, @y@ is flattened to yield an argument list of length 3, of which the first component of @x@ is passed as the first parameter of @h@, and the second component of @x@ and @y@ are structured into the second argument of type @[int, int]@.
+Finally, in the call to @h@, @x@ is flattened to yield an argument list of length 3, of which the first component of @x@ is passed as the first parameter of @h@, and the second component of @x@ and @y@ are structured into the second argument of type @[int, int]@.
 The flexible structure of tuples permits a simple and expressive function-call syntax to work seamlessly with both single- and multiple-return-value functions, and with any number of arguments of arbitrarily complex structure.
 
@@ -675,5 +675,5 @@
 // [x, y, z] = 1.5;
 _tuple3_(int, double, int) _tmp_stmtexpr_ret0;
-({
+({ // GNU C statement expression
   // assign LHS address temporaries
   int *__massassign_L0 = &x;    // ?{}
@@ -690,8 +690,8 @@
     int *__multassign_L2 = (int *)&_tmp_stmtexpr_ret0.2;       // ?{}
 
-    // assign RHS value temporaries and perform mass assignment to L0, L1, L2
-    int __multassign_R0 = (*__massassign_L0=(int)__massassign_R0);   // ?{}
-    double __multassign_R1 = (*__massassign_L1=__massassign_R0);     // ?{}
-    int __multassign_R2 = (*__massassign_L2=(int)__massassign_R0);   // ?{}
+    // assign RHS value temporaries and mass-assign to L0, L1, L2
+    int __multassign_R0 = (*__massassign_L0=(int)__massassign_R0); // ?{}
+    double __multassign_R1 = (*__massassign_L1=__massassign_R0);   // ?{}
+    int __multassign_R2 = (*__massassign_L2=(int)__massassign_R0); // ?{}
 
     // perform construction of statement expr return variable using
@@ -742,5 +742,5 @@
       _tmp_cp_ret0 :
       (_tmp_cp_ret0=f(), _unq0_finished_=1, _tmp_cp_ret0)).1; // ?{}
-  ({ // tuple destruction - destruct f() return temporary - tuple destruction
+  ({ // tuple destruction - destruct f() return temporary
     // assign LHS address temporaries
     double *__massassign_L3 = (double *)&_tmp_cp_ret0.0;  // ?{}
@@ -758,5 +758,5 @@
     int *__multassign_L5 = (int *)&_tmp_stmtexpr_ret0.2;       // ?{}
 
-    // assign RHS value temporaries and perform multiple assignment to L0, L1, L2
+    // assign RHS value temporaries and multiple-assign to L0, L1, L2
     int __multassign_R3 = (*__multassign_L0=(int)__multassign_R0);  // ?{}
     double __multassign_R4 = (*__multassign_L1=__multassign_R1);    // ?{}
Index: doc/rob_thesis/variadic.tex
===================================================================
--- doc/rob_thesis/variadic.tex	(revision 0eb185575bf22730aa7d4caf71c4758583ee159b)
+++ doc/rob_thesis/variadic.tex	(revision 67e8e192e166bc9a4f26b93a49b9bc8047bb10ad)
@@ -418,5 +418,6 @@
   *_p0; // ^?{}
 }
-void _thunk4(struct _conc__tuple2_0 _p0){ // void print([int, const char *])
+void _thunk4(struct _conc__tuple2_0 _p0){
+        // void print([int, const char *])
   struct _tuple1_ { // _tuple1_(T0)
     void *field_0;
@@ -428,5 +429,10 @@
     print_string(_pp0.field_0);  // print(rest.0)
   }
-  void _adapter_i_pii_(void (*_adaptee)(), void *_ret, void *_p0, void *_p1){
+  void _adapter_i_pii_(
+    void (*_adaptee)(),
+    void *_ret,
+    void *_p0,
+    void *_p1
+  ){
     *(int *)_ret=((int (*)(int *, int))_adaptee)(_p0, *(int *)_p1);
   }
@@ -438,5 +444,7 @@
   }
   void _adapter_tuple1_5_(void (*_adaptee)(), void *_p0){
-    ((void (*)(struct _conc__tuple1_1 ))_adaptee)(*(struct _conc__tuple1_1 *)_p0);
+    ((void (*)(struct _conc__tuple1_1 ))_adaptee)(
+      *(struct _conc__tuple1_1 *)_p0
+    );
   }
   print_variadic(
@@ -449,12 +457,12 @@
     sizeof(struct _conc__tuple1_1),
     __alignof__(struct _conc__tuple1_1),
-    (void *(*)(void *, void *))_assign_i,     // int ?=?(int *, int)
-    (void (*)(void *))_ctor_i,                // void ?{}(int *)
-    (void (*)(void *, void *))_ctor_ii,       // void ?{}(int *, int)
-    (void (*)(void *))_dtor_ii,               // void ^?{}(int *)
-    (void (*)(void *))print_int,              // void print(int)
-    (void (*)(void *))&_thunk5,               // void print([const char *])
-    &_p0.field_0,                             // rest.0
-    &(struct _conc__tuple1_1 ){ _p0.field_1 } // [rest.1]
+    (void *(*)(void *, void *))_assign_i,    // int ?=?(int *, int)
+    (void (*)(void *))_ctor_i,               // void ?{}(int *)
+    (void (*)(void *, void *))_ctor_ii,      // void ?{}(int *, int)
+    (void (*)(void *))_dtor_ii,              // void ^?{}(int *)
+    (void (*)(void *))print_int,             // void print(int)
+    (void (*)(void *))&_thunk5,              // void print([const char *])
+    &_p0.field_0,                            // rest.0
+    &(struct _conc__tuple1_1 ){ _p0.field_1 }// [rest.1]
   );
 }
@@ -480,5 +488,8 @@
 }
 void _adapter_pstring_string(void (*_adaptee)(), void *_p0, void *_p1){
-  ((void (*)(const char **, const char *))_adaptee)(_p0, *(const char **)_p1);
+  ((void (*)(const char **, const char *))_adaptee)(
+    _p0,
+    *(const char **)_p1
+  );
 }
 void _adapter_string_(void (*_adaptee)(), void *_p0){
@@ -486,5 +497,7 @@
 }
 void _adapter_tuple2_0_(void (*_adaptee)(), void *_p0){
-  ((void (*)(struct _conc__tuple2_0 ))_adaptee)(*(struct _conc__tuple2_0 *)_p0);
+  ((void (*)(struct _conc__tuple2_0 ))_adaptee)(
+    *(struct _conc__tuple2_0 *)_p0
+  );
 }
 print_variadic(
@@ -497,10 +510,10 @@
   sizeof(struct _conc__tuple2_0 ),
   __alignof__(struct _conc__tuple2_0 ),
-  (void *(*)(void *, void *))&_thunk0, // const char * ?=?(const char **, const char *)
-  (void (*)(void *))&_thunk1,          // void ?{}(const char **)
-  (void (*)(void *, void *))&_thunk2,  // void ?{}(const char **, const char *)
-  (void (*)(void *))&_thunk3,          // void ^?{}(const char **)
-  (void (*)(void *))print_string,      // void print(const char *)
-  (void (*)(void *))&_thunk4,          // void print([int, const char *])
+  &_thunk0,     // const char * ?=?(const char **, const char *)
+  &_thunk1,     // void ?{}(const char **)
+  &_thunk2,     // void ?{}(const char **, const char *)
+  &_thunk3,     // void ^?{}(const char **)
+  print_string, // void print(const char *)
+  &_thunk4,     // void print([int, const char *])
   &_temp0,                             // "x = "
   (({  // copy construct tuple argument to print
