Index: doc/theses/aaron_moss_PhD/phd/Makefile
===================================================================
--- doc/theses/aaron_moss_PhD/phd/Makefile	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ doc/theses/aaron_moss_PhD/phd/Makefile	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -1,8 +1,12 @@
-LATEX = pdflatex -interaction=nonstopmode
-BIBTEX = bibtex
+BUILD = build
+BIBDIR = ../../../bibliography
+TEXLIB = .:${BUILD}:${BIBDIR}:
+
+LATEX = TEXINPUTS=${TEXLIB} && export TEXINPUTS && pdflatex -interaction= -output-directory=${BUILD}
+BIBTEX = BIBINPUTS=${TEXLIB} && export BIBINPUTS && bibtex
 
 BASE = thesis
 DOCUMENT = ${BASE}.pdf
-AUX = ${BASE}.aux ${BASE}.bbl ${BASE}.blg ${BASE}.log ${BASE}.out ${BASE}.toc
+BIBFILE = ${BIBDIR}/pl.bib
 
 SOURCES = ${addsuffix .tex, \
@@ -23,16 +27,19 @@
 
 clean : 
-	@rm -frv ${DOCUMENT} ${AUX}
+	@rm -fv ${BUILD}/*
 
 wc :
 	wc ${SOURCES}
 
-${DOCUMENT} : ${SOURCES}
+${DOCUMENT} : ${SOURCES} ${BUILD}
 	${LATEX} ${BASE}
 	${LATEX} ${BASE}
 
-rebuild-refs : ${SOURCES} aaron-thesis.bib
+rebuild-refs : ${SOURCES} ${BIBFILE} ${BUILD}
 	${LATEX} ${BASE}
-	${BIBTEX} ${BASE}
+	${BIBTEX} ${BUILD}/${BASE}
 	${LATEX} ${BASE}
 	${LATEX} ${BASE}
+
+${BUILD}: 
+	mkdir -p ${BUILD}
Index: c/theses/aaron_moss_PhD/phd/aaron-thesis.bib
===================================================================
--- doc/theses/aaron_moss_PhD/phd/aaron-thesis.bib	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ 	(revision )
@@ -1,97 +1,0 @@
-%    Predefined journal names:
-%  acmcs: Computing Surveys		acta: Acta Infomatica
-@string{acta="Acta Infomatica"}
-%  cacm: Communications of the ACM
-%  ibmjrd: IBM J. Research & Development ibmsj: IBM Systems Journal
-%  ieeese: IEEE Trans. on Soft. Eng.	ieeetc: IEEE Trans. on Computers
-%  ieeetcad: IEEE Trans. on Computer-Aided Design of Integrated Circuits
-%  ipl: Information Processing Letters	jacm: Journal of the ACM
-%  jcss: J. Computer & System Sciences	scp: Science of Comp. Programming
-%  sicomp: SIAM J. on Computing		tocs: ACM Trans. on Comp. Systems
-%  tods: ACM Trans. on Database Sys.	tog: ACM Trans. on Graphics
-%  toms: ACM Trans. on Math. Software	toois: ACM Trans. on Office Info. Sys.
-%  toplas: ACM Trans. on Prog. Lang. & Sys.
-%  tcs: Theoretical Computer Science
-@string{ieeepds="IEEE Transactions on Parallel and Distributed Systems"}
-@string{ieeese="IEEE Transactions on Software Engineering"}
-@string{spe="Software---\-Practice and Experience"}
-@string{ccpe="Concurrency and Computation: Practice and Experience"}
-@string{sigplan="SIGPLAN Notices"}
-@string{joop="Journal of Object-Oriented Programming"}
-@string{popl="Conference Record of the ACM Symposium on Principles of Programming Languages"}
-@string{osr="Operating Systems Review"}
-@string{pldi="Programming Language Design and Implementation"}
-@string{toplas="Transactions on Programming Languages and Systems"}
-@string{mathann="Mathematische Annalen"}
-
-@mastersthesis{Bilson03,
-    keywords	= {Cforall, parametric polymorphism, overloading},
-    contributer	= {pabuhr@plg},
-    author	= {Richard C. Bilson},
-    title	= {Implementing Overloading and Polymorphism in \textsf{C}$\mathbf{\forall}$},
-    school	= {School of Computer Science, University of Waterloo},
-    year	= 2003,
-    address	= {Waterloo, Ontario, Canada, N2L 3G1},
-    note	= {\href{http://plg.uwaterloo.ca/theses/BilsonThesis.pdf}{http://\-plg.uwaterloo.ca/\-theses/\-BilsonThesis.pdf}},
-}
-
-@article{Buhr94a,
-    keywords	= {assignment, parameter passing, multiple assignment},
-    contributer	= {pabuhr@plg},
-    author	= {P. A. Buhr and David Till and C. R. Zarnke},
-    title	= {Assignment as the Sole Means of Updating Objects},
-    journal	= spe,
-    month	= sep,
-    year	= 1994,
-    volume	= 24,
-    number	= 9,
-    pages	= {835-870},
-}
-
-@mastersthesis{Delisle18,
-    author	= {Thierry Delisle },
-    title	= {Concurrency in \textsf{C}$\mathbf{\forall}$},
-    school	= {School of Computer Science, University of Waterloo},
-    year	= 2018,
-    address	= {Waterloo, Ontario, Canada, N2L 3G1},
-    note	= {\href{https://uwspace.uwaterloo.ca/handle/10012/12888}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-12888}},
-}
-
-@phdthesis{Ditchfield92,
-    keywords	= {C, parametric polymorphism, overloading},
-    contributer	= {pabuhr@plg},
-    author	= {Glen Jeffrey Ditchfield},
-    title	= {Contextual Polymorphism},
-    school	= {Department of Computer Science, University of Waterloo},
-    year	= 1992,
-    address	= {Waterloo, Ontario, Canada, N2L 3G1},
-    note	= {\href{http://plg.uwaterloo.ca/theses/DitchfieldThesis.pdf}{http://\-plg.uwaterloo.ca/\-theses/\-DitchfieldThesis.pdf}}
-}
-
-@article{Moss18,
-    keywords	= {concurrency, C++},
-    contributer	= {pabuhr@plg},
-    author	= {Aaron Moss and Robert Schluntz and Peter A. Buhr},
-    title	= {\textsf{C}$\mathbf{\forall}$ : Adding Modern Programming Language Features to C},
-    year	= 2018,
-    journal	= spe,
-    note	= {Accepted, to appear},
-}
-
-@mastersthesis{Schluntz17,
-    keywords 	= {constructors, destructors, tuples},
-    author	= {Robert Schluntz},
-    title	= {Resource Management and Tuples in \textsf{C}$\mathbf{\forall}$},
-    school	= {School of Computer Science, University of Waterloo},
-    year	= 2017,
-    address	= {Waterloo, Ontario, Canada, N2L 3G1},
-    note	= {\href{https://uwspace.uwaterloo.ca/handle/10012/11830}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-11830}},
-}
-
-@misc{TIOBE,
-    contributer	= {pabuhr@plg},
-    key		= {TIOBE Index},
-    title	= {{TIOBE} Index},
-    howpublished= {\href{http://www.tiobe.com/tiobe_index}{http://\-www.tiobe.com/\-tiobe\_index}},
-    optnote	= {Accessed: 2018-08},
-}
Index: doc/theses/aaron_moss_PhD/phd/background.tex
===================================================================
--- doc/theses/aaron_moss_PhD/phd/background.tex	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ doc/theses/aaron_moss_PhD/phd/background.tex	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -1,3 +1,3 @@
-\chapter{Background}
+\chapter{\CFA{}}
 
 \CFA{} adds a number of features to C, some of them providing significant increases to the expressive power of the language, but all designed to maintain the existing procedural programming paradigm of C and to be as orthogonal as possible to each other. 
@@ -21,5 +21,5 @@
 It is important to note that \CFA{} is not an object-oriented language. 
 This is a deliberate choice intended to maintain the applicability of the mental model and language idioms already possessed by C programmers. 
-This choice is in marked contrast to \CC{}, which, though it has backward-compatibility with C on the source code level, is a much larger and more complex language, and requires extensive developer re-training before they can write idiomatic, efficient code in \CC{}'s object-oriented paradigm.
+This choice is in marked contrast to \CC{}, which, though it has backward-compatibility with C on the source code level, is a much larger and more complex language, and requires extensive developer re-training to write idiomatic, efficient code in \CC{}'s object-oriented paradigm.
 
 \CFA{} does have a system of implicit type conversions derived from C's ``usual arithmetic conversions''; while these conversions may be thought of as something like an inheritance hierarchy, the underlying semantics are significantly different and such an analogy is loose at best. 
@@ -62,9 +62,9 @@
 struct counter { int x; };
 
-counter& `++?`(counter& c) { ++c.x; return c; }  $\C{// pre-increment}$
-counter `?++`(counter& c) {  $\C{// post-increment}$
+counter& `++?`(counter& c) { ++c.x; return c; }  $\C[2in]{// pre-increment}$
+counter `?++`(counter& c) {  $\C[2in]{// post-increment}$
 	counter tmp = c; ++c; return tmp;
 }
-bool `?<?`(const counter& a, const counter& b) {  $\C{// comparison}$
+bool `?<?`(const counter& a, const counter& b) {  $\C[2in]{// comparison}$
 	return a.x < b.x;
 }
@@ -73,5 +73,21 @@
 Together, \CFA{}'s backward-compatibility with C and the inclusion of this operator overloading feature imply that \CFA{} must select among function overloads using a method compatible with C's ``usual arithmetic conversions''\cit{}, so as to present user programmers with only a single set of overloading rules.
 
-\subsection{Polymorphic Functions}
+\subsubsection{Special Literal Types}
+
+Literal !0! is also used polymorphically in C; it may be either integer zero or the null value of any pointer type. 
+\CFA{} provides a special type for the !0! literal, !zero_t!, so that users can define a zero value for their own types without being forced to create a conversion from an integer or pointer type (though \CFA{} also includes implicit conversions from !zero_t! to the integer and pointer types for backward compatibility). 
+
+According to the C standard\cit{}, !0! is the only false value; any value that compares equal to zero is false, while any value that does not is true. 
+By this rule, boolean contexts such as !if ( x )! can always be equivalently rewritten as \lstinline{if ( (x) != 0 )}. 
+\CFACC{} applies this rewriting in all boolean contexts, so any type !T! can be made ``truthy'' (that is, given a boolean interpretation) in \CFA{} by defining an operator overload \lstinline{int ?!=?(T, zero_t)}; unlike \CC{} prior to the addition of explicit casts in \CCeleven{}, this design does not add comparability or convertablity to arbitrary integer types. 
+
+\CFA{} also includes a special type for !1!, !one_t!; like !zero_t!, !one_t! has built-in implicit conversions to the various integral types so that !1! maintains its expected semantics in legacy code. 
+The addition of !one_t! allows generic algorithms to handle the unit value uniformly for types where it is meaningful; a simple example of this is that polymorphic functions\footnote{discussed in Section~\ref{poly-func-sec}} in the \CFA{} prelude define !++x! and !x++! in terms of !x += 1!, allowing users to idiomatically define all forms of increment for a type !T! by defining the single function !T& ?+=?(T&, one_t)!; analogous overloads for the decrement operators are also present, and programmers can override any of these functions for a particular type if desired.
+
+\CFA{} previously allowed !0! and !1! to be the names of polymorphic variables, with separate overloads for !int 0!, !int 1!, and !forall(dtype T) T* 0!. 
+As revealed in my own work on generic types (Chapter~\ref{generic-chap}), the parameteric polymorphic zero variable was not generalizable to other types; though all null pointers have the same in-memory representation, the same cannot be said of the zero values of arbitrary types. 
+As such, variables that could represent !0! and !1! were phased out in favour of functions that could generate those values for a given type as appropriate.
+
+\subsection{Polymorphic Functions} \label{poly-func-sec}
 
 The most significant feature \CFA{} adds is parametric-polymorphic functions. 
@@ -91,5 +107,5 @@
 One benefit of this design is that it allows polymorphic functions to be separately compiled. 
 The forward declaration !forall(otype T) T identity(T);! uniquely defines a single callable function, which may be implemented in a different file. 
-The fact that there is only one implementation of each polymorphic function also reduces compile times relative to the template-expansion approach taken by \CC{}, as well as reducing binary sizes and runtime pressure on instruction cache at by re-using a single version of each function.
+The fact that there is only one implementation of each polymorphic function also reduces compile times relative to the template-expansion approach taken by \CC{}, as well as reducing binary sizes and runtime pressure on instruction cache by re-using a single version of each function.
 
 \subsubsection{Type Assertions}
@@ -117,10 +133,10 @@
 
 This version of !twice! works for any type !S! that has an addition operator defined for it, and it could be used to satisfy the type assertion on !four_times!. 
-\CFACC{} accomplishes this by creating a wrapper function calling !twice // (2)! with !S! bound to !double!, then providing this wrapper function to !four_times!\footnote{\lstinline{twice // (2)} could also have had a type parameter named \lstinline{T}; \CFA{} specifies renaming of the type parameters, which would avoid the name conflict with the type variable \lstinline{T} of \lstinline{four_times}}.
-
-Finding appropriate functions to satisfy type assertions is essentially a recursive case of expression resolution, as it takes a name (that of the type assertion) and attempts to match it to a suitable declaration \emph{in the current scope}. 
-If a polymorphic function can be used to satisfy one of its own type assertions, this recursion may not terminate, as it is possible that that function is examined as a candidate for its own type assertion unboundedly repeatedly. 
+\CFACC{} accomplishes this by creating a wrapper function calling !twice//(2)! with !S! bound to !double!, then providing this wrapper function to !four_times!\footnote{\lstinline{twice // (2)} could also have had a type parameter named \lstinline{T}; \CFA{} specifies renaming of the type parameters, which would avoid the name conflict with the type variable \lstinline{T} of \lstinline{four_times}}.
+
+Finding appropriate functions to satisfy type assertions is essentially a recursive case of expression resolution, as it takes a name (that of the type assertion) and attempts to match it to a suitable declaration in the current scope. 
+If a polymorphic function can be used to satisfy one of its own type assertions, this recursion may not terminate, as it is possible that that function is examined as a candidate for its own assertion unboundedly repeatedly. 
 To avoid such infinite loops, \CFACC{} imposes a fixed limit on the possible depth of recursion, similar to that employed by most \CC{} compilers for template expansion; this restriction means that there are some semantically well-typed expressions that cannot be resolved by \CFACC{}.
-\TODO{Update this with final state} One contribution made in the course of this thesis was modifying \CFACC{} to use the more flexible expression resolution algorithm for assertion matching, rather than the previous simpler approach of unification on the types of the functions.
+\TODO{Update this with final state} One contribution made in the course of this thesis was modifying \CFACC{} to use the more flexible expression resolution algorithm for assertion matching, rather than the simpler but limited previous approach of unification on the types of the functions.
 
 \subsubsection{Deleted Declarations}
@@ -175,10 +191,10 @@
 \begin{cfa}
 trait pointer_like(`otype Ptr, otype El`) {
-	El& *?(Ptr);  $\C{Ptr can be dereferenced to El}$
+	El& *?(Ptr);  $\C{// Ptr can be dereferenced to El}$
 };
 
 struct list {
 	int value;
-	list* next; $\C{may omit struct on type names}$
+	list* next; $\C{// may omit struct on type names}$
 };
 
@@ -200,6 +216,6 @@
 
 In addition to the multiple interpretations of an expression produced by name overloading and polymorphic functions, for backward compatibility \CFA{} must support all of the implicit conversions present in C, producing further candidate interpretations for expressions. 
-As mentioned above, C does not have an inheritance hierarchy of types, but the C standard's rules for the ``usual arithmetic conversions''\cit{} define which of the built-in tyhpes are implicitly convertable to which other types, and the relative cost of any pair of such conversions from a single source type. 
-\CFA{} adds to the usual arithmetic conversions rules defining the cost of binding a polymorphic type variable in a function call; such bindings are cheaper than any \emph{unsafe} (narrowing) conversion, \eg{} !int! to !char!, but more expensive than any \emph{safe} (widening) conversion, \eg{} !int! to !double!. 
+As mentioned above, C does not have an inheritance hierarchy of types, but the C standard's rules for the ``usual arithmetic conversions'\cit{} define which of the built-in types are implicitly convertible to which other types, and the relative cost of any pair of such conversions from a single source type. 
+\CFA{} adds rules to the usual arithmetic conversions defining the cost of binding a polymorphic type variable in a function call; such bindings are cheaper than any \emph{unsafe} (narrowing) conversion, \eg{} !int! to !char!, but more expensive than any \emph{safe} (widening) conversion, \eg{} !int! to !double!. 
 One contribution of this thesis, discussed in Section \TODO{add to resolution chapter}, is a number of refinements to this cost model to more efficiently resolve polymorphic function calls. 
 
@@ -208,14 +224,132 @@
 Note that which subexpression interpretation is minimal-cost may require contextual information to disambiguate. 
 For instance, in the example in Section~\ref{overloading-sec}, !max(max, -max)! cannot be unambiguously resolved, but !int m = max(max, -max)! has a single minimal-cost resolution. 
-While the interpretation !int m = (int)max((double)max, -(double)max)! is also a valid interpretation, it is not minimal-cost due to the unsafe cast from the !double! result of !max! to the !int!\footnote{The two \lstinline{double} casts function as type ascriptions selecting \lstinline{double max} rather than casts from \lstinline{int max} to \lstinline{double}, and as such are zero-cost.}. 
-These contextual effects make the expression resolution problem for \CFA{} both theoretically and practically difficult, but the observation driving the work in Chapter~\ref{resolution-chap} is that of the many top-level expressions in a given program, most will likely be straightforward and idiomatic so that programmers writing and maintaining the code can easily understand them; it follows that effective heuristics for common cases can bring down compiler runtime enough that a small proportion of harder-to-resolve expressions should not increase compiler runtime or memory usage inordinately.
+While the interpretation !int m = (int)max((double)max, -(double)max)! is also a valid interpretation, it is not minimal-cost due to the unsafe cast from the !double! result of !max! to !int!\footnote{The two \lstinline{double} casts function as type ascriptions selecting \lstinline{double max} rather than casts from \lstinline{int max} to \lstinline{double}, and as such are zero-cost.}. 
+These contextual effects make the expression resolution problem for \CFA{} both theoretically and practically difficult, but the observation driving the work in Chapter~\ref{resolution-chap} is that of the many top-level expressions in a given program, most are straightforward and idiomatic so that programmers writing and maintaining the code can easily understand them; it follows that effective heuristics for common cases can bring down compiler runtime enough that a small proportion of harder-to-resolve expressions does not inordinately increase overall compiler runtime or memory usage.
 
 \subsection{Type Features} \label{type-features-sec}
 
+The name overloading and polymorphism features of \CFA{} have the greatest effect on language design and compiler runtime, but there are a number of other features in the type system which have a smaller effect but are useful for code examples. 
+These features are described here. 
+
 \subsubsection{Reference Types}
 
-% TODO mention contribution on reference rebind
-
-\subsubsection{Lifetime Management}
-
-\subsubsection{0 and 1 Literals}
+One of the key ergonomic improvements in \CFA{} is reference types, designed and implemented by Robert Schluntz\cite{Schluntz17}. 
+Given some type !T!, a !T&! (``reference to !T!'') is essentially an automatically dereferenced pointer. 
+These types allow seamless pass-by-reference for function parameters, without the extraneous dereferencing syntax present in C; they also allow easy easy aliasing of nested values with a similarly convenient syntax. 
+A particular improvement is removing syntactic special cases for operators which take or return mutable values; for example, the use !a += b! of a compound assignment operator now matches its signature, !int& ?+=?(int&, int)!, as opposed to the previous syntactic special cases to automatically take the address of the first argument to !+=! and to mark its return value as mutable.
+
+The C standard makes heavy use of the concept of \emph{lvalue}, an expression with a memory address; its complement, \emph{rvalue} (a non-addressable expression) is not explicitly named. 
+In \CFA{}, the distinction between lvalue and rvalue can be reframed in terms of reference and non-reference types, with the benefit of being able to express the difference in user code. 
+\CFA{} references preserve the existing qualifier-dropping implicit lvalue-to-rvalue conversion from C (\eg{} a !const volatile int&! can be implicitly copied to a bare !int!)
+To make reference types more easily usable in legacy pass-by-value code, \CFA{} also adds an implicit rvalue-to-lvalue conversion, implemented by storing the value in a fresh compiler-generated temporary variable and passing a reference to that temporary. 
+To mitigate the ``!const! hell'' problem present in \CC{}, there is also a qualifier-dropping lvalue-to-lvalue conversion, also implemented by copying into a temporary:
+
+\begin{cfa}
+const int magic = 42;
+
+void inc_print( int& x ) { printf("%d\n", ++x); }
+
+print_inc( magic ); $\C{// legal; implicitly generated code in red below:}$
+
+`int tmp = magic;` $\C{// to safely strip const-qualifier}$
+`print_inc( tmp );` $\C{// tmp is incremented, magic is unchanged}$
+\end{cfa}
+
+Despite the similar syntax, \CFA{} references are significantly more flexible than \CC{} references. 
+The primary issue with \CC{} references is that it is impossible to extract the address of the reference variable rather than the address of the referred-to variable. 
+This breaks a number of the usual compositional properties of the \CC{} type system, \eg{} a reference cannot be re-bound to another variable, nor is it possible to take a pointer to, array of, or reference to a reference. 
+\CFA{} supports all of these use cases \TODO{test array} without further added syntax. 
+The key to this syntax-free feature support is an observation made by the author that the address of a reference is a lvalue. 
+In C, the address-of operator !&x! can only be applied to lvalue expressions, and always produces an immutable rvalue; \CFA{} supports reference re-binding by assignment to the address of a reference, and pointers to references by repeating the address-of operator:
+
+\begin{cfa}
+int x = 2, y = 3;
+int& r = x;  $\C{// r aliases x}$
+&r = &y; $\C{// r now aliases y}$
+int** p = &&r; $\C{// p points to r}$
+\end{cfa}
+
+For better compatibility with C, the \CFA{} team has chosen not to differentiate function overloads based on top-level reference types, and as such their contribution to the difficulty of \CFA{} expression resolution is largely restricted to the implementation details of normalization conversions and adapters. 
+
+\subsubsection{Resource Management}
+
+\CFA{} also supports the RAII (``Resource Acquisition is Initialization'') idiom originated by \CC{}, thanks to the object lifetime work of Robert Schluntz\cite{Schluntz17}. 
+This idiom allows a safer and more principled approach to resource management by tying acquisition of a resource to object initialization, with the corresponding resource release executed automatically at object finalization. 
+A wide variety of conceptual resources may be conveniently managed by this scheme, including heap memory, file handles, and software locks. 
+
+\CFA{}'s implementation of RAII is based on special constructor and destructor operators, available via the !x{ ... }! constructor syntax and !^x{ ... }! destructor syntax. 
+Each type has an overridable compiler-generated zero-argument constructor, copy constructor, assignment operator, and destructor, as well as a field-wise constructor for each appropriate prefix of the member fields of !struct! types. 
+For !struct! types the default versions of these operators call their equivalents on each field of the !struct!. 
+The main implication of these object lifetime functions for expression resolution is that they are all included as implicit type assertions for !otype! type variables, with a secondary effect being an increase in code size due to the compiler-generated operators. 
+Due to these implicit type assertions, assertion resolution is pervasive in \CFA{} polymorphic functions, even those without explicit type assertions. 
+Implicitly-generated code is shown in red in the following example:
+
+\begin{cfa}
+struct kv {
+	int key;
+	char* value;
+};
+
+`void ?{} (kv& this) {` $\C[3in]{// default constructor}$
+`	this.key{};` $\C[3in]{// call recursively on members}$
+`	this.value{};
+}
+
+void ?{} (kv& this, int key) {` $\C[3in]{// partial field constructor}$
+`	this.key{ key };
+	this.value{};` $\C[3in]{// default-construct missing fields}$
+`}
+
+void ?{} (kv& this, int key, char* value) {` $\C[3in]{// complete field constructor}$
+`	this.key{ key };
+	this.value{ value };
+}
+
+void ?{} (kv& this, kv that) {` $\C[3in]{// copy constructor}$
+`	this.key{ that.key };
+	this.value{ that.value };
+}
+
+kv ?=? (kv& this, kv that) {` $\C[3in]{// assignment operator}$
+`	this.key = that.key;
+	this.value = that.value;
+}
+
+void ^?{} (kv& this) {` $\C[3in]{// destructor}$
+`	^this.key{};
+	^this.value{};
+}`
+
+forall(otype T `| { void ?{}(T&); void ?{}(T&, T); T ?=?(T&, T); void ^?{}(T&); }`)
+void foo(T);
+\end{cfa}
+
+\subsubsection{Tuple Types}
+
+\CFA{} adds \emph{tuple types} to C, a syntactic facility for referring to lists of values anonymously or with a single identifier. 
+An identifier may name a tuple, a function may return one, and a tuple may be implicitly \emph{destructured} into its component values. 
+The implementation of tuples in \CFACC{}'s code generation is based on the generic types introduced in Chapter~\ref{generic-chap}, with one compiler-generated generic type for each tuple arity. 
+This allows tuples to take advantage of the same runtime optimizations available to generic types, while reducing code bloat. 
+An extended presentation of the tuple features of \CFA{} can be found in \cite{Moss18}, but the following example shows the basics:
+
+\begin{cfa}
+[char, char] x = ['!', '?']; $\C{// (1); tuple type and expression syntax}$
+int x = 2; $\C{// (2)}$
+
+forall(otype T)
+[T, T] swap( T a, T b ) { $\C{// (3)}$
+	return [b, a]; $\C{// one-line swap syntax}$
+}
+
+x = swap( x ); $\C{// destructure [char, char] x into two elements}$
+$\C{// cannot use int x, not enough arguments}$
+
+void swap( int, char, char ); $\C{// (4)}$
+
+swap( x, x ); $\C{// (4) on (2), (1)}$
+$\C{// not (3) on (2), (2) due to polymorphism cost}$
+\end{cfa}
+
+Tuple destructuring breaks the one-to-one relationship between identifiers and values. 
+This precludes some argument-parameter matching strategies for expression resolution, as well as cheap interpretation filters based on comparing number of parameters and arguments. 
+As an example, in the call to !swap( x, x )! above, the second !x! can be resolved starting at the second or third parameter of !swap!, depending which interpretation of !x! was chosen for the first argument.
Index: doc/theses/aaron_moss_PhD/phd/cfa-macros.tex
===================================================================
--- doc/theses/aaron_moss_PhD/phd/cfa-macros.tex	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ doc/theses/aaron_moss_PhD/phd/cfa-macros.tex	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -20,5 +20,5 @@
 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
 
-\newcommand{\C}[2][2in]{\hfill\makebox[#1][l]{\LstCommentStyle{#2}}}
+\newcommand{\C}[2][3.5in]{\hfill\makebox[#1][l]{\LstCommentStyle{#2}}}
 
 % CFA programming language, based on ANSI C (with some gcc additions)
Index: doc/theses/aaron_moss_PhD/phd/generic-types.tex
===================================================================
--- doc/theses/aaron_moss_PhD/phd/generic-types.tex	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ doc/theses/aaron_moss_PhD/phd/generic-types.tex	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -4,5 +4,10 @@
 Talk about generic types. Pull from Moss~\etal\cite{Moss18}.
 
+% TODO discuss layout function algorithm, application to separate compilation
+% TODO put a static const field in for _n_fields for each generic, describe utility for separate compilation
+
 % TODO mention impetus for zero_t design
 
 % TODO mention use in tuple-type implementation
+
+% TODO pull benchmarks from Moss et al.
Index: doc/theses/aaron_moss_PhD/phd/thesis.tex
===================================================================
--- doc/theses/aaron_moss_PhD/phd/thesis.tex	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ doc/theses/aaron_moss_PhD/phd/thesis.tex	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -141,5 +141,5 @@
 \addcontentsline{toc}{chapter}{\textbf{References}}
 
-\bibliography{aaron-thesis}
+\bibliography{pl}
 % Tip 5: You can create multiple .bib files to organize your references. 
 % Just list them all in the \bibliogaphy command, separated by commas (no spaces).
Index: libcfa/configure
===================================================================
--- libcfa/configure	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ libcfa/configure	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -1959,4 +1959,5 @@
 
 
+
 am__api_version='1.15'
 
Index: src/CodeTools/ResolvProtoDump.cc
===================================================================
--- src/CodeTools/ResolvProtoDump.cc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
+++ src/CodeTools/ResolvProtoDump.cc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -0,0 +1,734 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ResolvProtoDump.cc -- Translates CFA resolver instances into resolv-proto instances
+//
+// Author           : Aaron Moss
+// Created On       : Tue Sep 11 09:04:00 2018
+// Last Modified By : Aaron Moss
+// Last Modified On : Tue Sep 11 09:04:00 2018
+// Update Count     : 1
+//
+
+#include <algorithm>
+#include <cctype>
+#include <iostream>
+#include <memory>
+#include <list>
+#include <set>
+#include <sstream>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "Common/PassVisitor.h"
+#include "Common/utility.h"
+#include "CodeGen/OperatorTable.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Type.h"
+
+namespace CodeTools {
+
+	/// Visitor for dumping resolver prototype output
+	class ProtoDump : public WithShortCircuiting, public WithVisitorRef<ProtoDump> {
+		std::set<std::string> decls;             ///< Declarations in this scope
+		std::vector<std::string> exprs;          ///< Expressions in this scope
+		std::vector<ProtoDump> subs;             ///< Sub-scopes
+		std::unordered_set<std::string> closed;  ///< Closed type variables
+		const ProtoDump* parent;                 ///< Outer lexical scope
+		std::unique_ptr<Type> rtnType;           ///< Return type for this scope
+
+	public:
+		/// Default constructor for root ProtoDump
+		ProtoDump() : decls(), exprs(), subs(), closed(), parent(nullptr), rtnType(nullptr) {}
+
+		/// Child constructor
+		ProtoDump(const ProtoDump* p, Type* r) 
+			: decls(), exprs(), subs(), closed(p->closed), parent(p), rtnType(r) {}
+
+		// Fix copy issues
+		ProtoDump(const ProtoDump& o) 
+			: decls(o.decls), exprs(o.exprs), subs(o.subs), closed(o.closed), parent(o.parent), 
+			  rtnType(maybeClone(o.rtnType.get())) {}
+		ProtoDump( ProtoDump&& ) = default;
+
+		ProtoDump& operator= (const ProtoDump& o) {
+			if ( this == &o ) return *this;
+
+			decls = o.decls;
+			exprs = o.exprs;
+			subs = o.subs;
+			closed = o.closed;
+			parent = o.parent;
+			rtnType.reset( maybeClone(o.rtnType.get()) );
+			
+			return *this;
+		}
+		ProtoDump& operator= (ProtoDump&&) = default;
+
+	private:
+		/// checks if this declaration is contained in the scope or one of its parents
+		bool hasDecl( const std::string& s ) const {
+			if ( decls.count( s ) ) return true;
+			if ( parent ) return parent->hasDecl( s );
+			return false;
+		}
+
+		/// adds a new declaration to this scope, providing it does not already exist
+		void addDecl( const std::string& s ) {
+			if ( ! hasDecl( s ) ) decls.insert( s );
+		}
+
+		/// adds a new expression to this scope
+		void addExpr( const std::string& s ) {
+			if ( ! s.empty() ) { exprs.emplace_back( s ); }
+		}
+
+		/// adds a new subscope to this scope, returning a reference
+		void addSub( PassVisitor<ProtoDump>&& sub ) {
+			subs.emplace_back( std::move(sub.pass) );
+		}
+	
+		/// Whether lists should be separated, terminated, or preceded by their separator
+		enum septype { separated, terminated, preceded };
+
+		/// builds space-separated list of types
+		template<typename V>
+		static void build( V& visitor, const std::list< Type* >& tys, std::stringstream& ss, 
+				septype mode = separated ) {
+			if ( tys.empty() ) return;
+
+			if ( mode == preceded ) { ss << ' '; }
+
+			auto it = tys.begin();
+			(*it)->accept( visitor );
+
+			while ( ++it != tys.end() ) {
+				ss << ' ';
+				(*it)->accept( visitor );
+			}
+
+			if ( mode == terminated ) { ss << ' '; }
+		}
+
+		/// builds list of types wrapped as tuple type
+		template<typename V>
+		static void buildAsTuple( V& visitor, const std::list< Type* >& tys, 
+				std::stringstream& ss ) {
+			switch ( tys.size() ) {
+				case 0: ss << "#void"; break;
+				case 1: tys.front()->accept( visitor ); break;
+				default:
+					ss << "#$" << tys.size() << '<';
+					build( visitor, tys, ss );
+					ss << '>';
+					break;
+			}
+		}
+
+		/// gets types from DWT list
+		static std::list< Type* > from_decls( const std::list< DeclarationWithType* >& decls ) {
+			std::list< Type* > tys;
+			for ( auto decl : decls ) { tys.emplace_back( decl->get_type() ); }
+			return tys;
+		}
+
+		/// gets types from TypeExpr list
+		static std::list< Type* > from_exprs( const std::list< Expression* >& exprs ) {
+			std::list< Type* > tys;
+			for ( auto expr : exprs ) {
+				if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(expr) ) {
+					tys.emplace_back( tyExpr->type );
+				}
+			}
+			return tys;
+		}
+
+		/// builds prefixes for rp_name
+		static std::string new_prefix( const std::string& old, const char* added ) {
+			if ( old.empty() ) return std::string{"$"} + added;
+			return old + added;
+		}
+
+		/// shortens operator names
+		static void op_name( const std::string& name, std::stringstream& ss ) {
+			if ( name.compare( 0, 10, "_operator_" ) == 0 ) {
+				ss << name.substr(10);
+			} else if ( name.compare( "_constructor" ) == 0 
+					|| name.compare( "_destructor" ) == 0 ) {
+				ss << name.substr(1);
+			} else if ( name.compare( 0, 11, "__operator_" ) == 0 ) {
+				ss << name.substr(11);
+			} else {
+				ss << name;
+			}
+		}
+
+		/// replaces operators with resolv-proto names
+		static void rp_name( const std::string& name, std::stringstream& ss, 
+				std::string&& pre = "" ) {
+			// safety check for anonymous names
+			if ( name.empty() ) {
+				ss << new_prefix(pre, "anon");
+				return;
+			}
+
+			// replace operator names
+			CodeGen::OperatorInfo info;
+			if ( CodeGen::operatorLookup( name, info ) ) {
+				ss << new_prefix(pre, "");
+				op_name( info.outputName, ss );
+				return;
+			} 
+			
+			// replace retval names
+			if ( name.compare( 0, 8, "_retval_" ) == 0 ) {
+				ss << new_prefix(pre, "rtn_");
+				op_name( name.substr(8), ss );
+				return;
+			}
+			
+			// default to just name, with first character in lowercase
+			ss << pre 
+			   << (char)std::tolower( static_cast<unsigned char>(name[0]) )
+			   << (name.c_str() + 1);
+		}
+
+		/// ensures type inst names are uppercase
+		static void ti_name( const std::string& name, std::stringstream& ss ) {
+			unsigned i = 0;
+			while ( i < name.size() && name[i] == '_' ) { ++i; }
+			if ( i == name.size() ) {
+				ss << "Anon";
+				return;
+			}
+			ss << (char)std::toupper( static_cast<unsigned char>(name[i]) )
+			   << (name.c_str() + i + 1);
+		}
+
+		/// Visitor for printing types
+		struct TypePrinter : public WithShortCircuiting, WithVisitorRef<TypePrinter>, WithGuards {
+			std::stringstream& ss;                          ///< Output to print to
+			const std::unordered_set<std::string>& closed;  ///< Closed type variables
+			unsigned depth;                                 ///< Depth of nesting from root type
+
+			TypePrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss ) 
+				: ss(ss), closed(closed), depth(0) {}
+
+			// basic type represented as integer type
+			// TODO maybe hard-code conversion graph and make named type
+			void previsit( BasicType* bt ) { ss << (int)bt->get_kind(); }
+
+			// pointers (except function pointers) represented as generic type
+			void previsit( PointerType* pt ) {
+				if ( ! dynamic_cast<FunctionType*>(pt->base) ) { ss << "#$ptr<"; ++depth; }
+			}
+			void postvisit( PointerType* pt ) {
+				if ( ! dynamic_cast<FunctionType*>(pt->base) ) { --depth; ss << '>'; }
+			}
+
+			// arrays represented as generic pointers
+			void previsit( ArrayType* at ) {
+				ss << "#$ptr<";
+				++depth;
+				at->base->accept( *visitor );
+				--depth;
+				ss << '>';
+				visit_children = false;
+			}
+
+			// ignore top-level reference types, they're mostly transparent to resolution
+			void previsit( ReferenceType* ) {
+				if ( depth > 0 ) { ss << "#$ref<"; }
+				++depth;
+			}
+			void postvisit( ReferenceType* ) {
+				--depth;
+				if ( depth > 0 ) { ss << '>'; }
+			}
+
+			// print function types using prototype syntax
+			void previsit( FunctionType* ft ) {
+				ss << '[';
+				++depth;
+				build( *visitor, from_decls( ft->returnVals ), ss, preceded );
+				ss << " : ";
+				build( *visitor, from_decls( ft->parameters ), ss, terminated );
+				--depth;
+				ss << ']';
+				visit_children = false;
+			}
+
+		private:
+			// prints aggregate type name as NamedType with optional paramters
+			void handleAggregate( ReferenceToType* at ) {
+				ss << '#' << at->name;
+				if ( ! at->parameters.empty() ) {
+					ss << '<';
+					++depth;
+					build( *visitor, from_exprs( at->parameters ), ss );
+					--depth;
+					ss << '>';
+				}
+				visit_children = false;
+			}
+
+		public:
+			// handle aggregate types using NamedType
+			void previsit( StructInstType* st ) { handleAggregate( st ); }
+			void previsit( UnionInstType* ut ) { handleAggregate( ut ); }
+
+			// replace enums with int
+			void previsit( EnumInstType* ) { ss << (int)BasicType::SignedInt; }
+
+			void previsit( TypeInstType* vt ) {
+				// print closed variables as named types
+				if ( closed.count( vt->name ) ) { ss << '#' << vt->name; }
+				// otherwise make sure first letter is capitalized
+				else { ti_name( vt->name, ss ); }
+			}
+
+			// flattens empty and singleton tuples
+			void previsit( TupleType* tt ) {
+				++depth;
+				buildAsTuple( *visitor, tt->types, ss );
+				--depth;
+				visit_children = false;
+			}
+
+			// TODO support VarArgsType
+
+			// replace 0 and 1 with int
+			// TODO support 0 and 1 with their proper type names and conversions
+			void previsit( ZeroType* ) { ss << (int)BasicType::SignedInt; }
+			void previsit( OneType* ) { ss << (int)BasicType::SignedInt; }
+
+			// only print void type if not at top level
+			void previsit( VoidType* ) {
+				if ( depth > 0 ) { ss << "#void"; }
+			}
+		};
+	
+		/// builds description of function
+		void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
+			PassVisitor<TypePrinter> printTy{ closed, ss };
+			// print return values
+			build( printTy, from_decls( fnTy->returnVals ), ss, terminated );
+			// print name
+			rp_name( name, ss );
+			// print parameters
+			build( printTy, from_decls( fnTy->parameters ), ss, preceded );
+			// print assertions
+			for ( TypeDecl* tyvar : fnTy->forall ) {
+				for ( DeclarationWithType* assn : tyvar->assertions ) {
+					ss << " | "; 
+					build( assn->name, assn->get_type(), ss );
+				}
+			}
+		}
+
+		/// builds description of a variable (falls back to function if function type)
+		void build( const std::string& name, Type* ty, std::stringstream& ss ) {
+			// ignore top-level references
+			Type *norefs = ty->stripReferences();
+			
+			// fall back to function declaration if function type
+			if ( PointerType* pTy = dynamic_cast< PointerType* >(norefs) ) {
+				if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(pTy->base) ) {
+					build( name, fnTy, ss );
+					return;
+				}
+			} else if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(norefs) ) {
+				build( name, fnTy, ss );
+				return;
+			}
+
+			// print variable declaration in prototype syntax
+			PassVisitor<TypePrinter> printTy{ closed, ss };
+			norefs->accept( printTy );
+			ss << " &";
+			rp_name( name, ss );
+		}
+
+		/// builds description of a field access
+		void build( const std::string& name, AggregateDecl* agg, Type* ty, std::stringstream& ss ) {
+			// ignore top-level references
+			Type *norefs = ty->stripReferences();
+
+			// print access as new field name
+			PassVisitor<TypePrinter> printTy{ closed, ss };
+			norefs->accept( printTy );
+			ss << ' ';
+			rp_name( name, ss, "$field_" );
+			ss << " #" << agg->name;
+			// handle type parameters
+			if ( ! agg->parameters.empty() ) {
+				ss << '<';
+				auto it = agg->parameters.begin();
+				while (true) {
+					ti_name( (*it)->name, ss );
+					if ( ++it == agg->parameters.end() ) break;
+					ss << ' ';
+				}
+				ss << '>';
+			}
+		}
+
+		/// Visitor for printing expressions
+		struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
+			// TODO change interface to generate multiple expression candidates
+			const std::unordered_set<std::string>& closed;  ///< set of closed type vars
+			std::stringstream& ss;                          ///< Output to print to
+
+			ExprPrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss ) 
+				: closed(closed), ss(ss) {}
+
+			/// Names handled as name expressions
+			void previsit( NameExpr* expr ) {
+				ss << '&';
+				rp_name( expr->name, ss );
+			}
+
+			/// Calls handled as calls
+			void previsit( UntypedExpr* expr ) {
+				// TODO handle name extraction more generally
+				NameExpr* name = dynamic_cast<NameExpr*>(expr->function);
+
+				// fall back on just resolving call to function name
+				// TODO incorporate function type into resolv-proto
+				if ( ! name ) {
+					expr->function->accept( *visitor );
+					visit_children = false;
+					return;
+				}
+
+				rp_name( name->name, ss );
+				if ( expr->args.empty() ) {
+					ss << "()";
+				} else {
+					ss << "( ";
+					auto it = expr->args.begin();
+					while (true) {
+						(*it)->accept( *visitor );
+						if ( ++it == expr->args.end() ) break;
+						ss << ' ';
+					}
+					ss << " )";
+				}
+				visit_children = false;
+			}
+
+			/// Already-resolved calls skipped
+			void previsit( ApplicationExpr* ) {
+				visit_children = false;
+			}
+
+			/// Address-of handled as operator
+			void previsit( AddressExpr* expr ) {
+				ss << "$addr( ";
+				expr->arg->accept( *visitor );
+				ss << " )";
+				visit_children = false;
+			}
+
+			/// Casts replaced with result type
+			/// TODO put cast target functions in, and add second expression for target
+			void previsit( CastExpr* cast ) {
+				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
+				cast->result->accept( tyPrinter );
+				visit_children = false;
+			}
+			
+			/// Member access handled as function from aggregate to member
+			void previsit( UntypedMemberExpr* expr ) {
+				// TODO handle name extraction more generally
+				NameExpr* name = dynamic_cast<NameExpr*>(expr->member);
+
+				// fall back on just resolving call to member name
+				// TODO incorporate function type into resolv-proto
+				if ( ! name ) {
+					expr->member->accept( *visitor );
+					visit_children = false;
+					return;
+				}
+
+				rp_name( name->name, ss, "$field_" );
+				ss << "( ";
+				expr->aggregate->accept( *visitor );
+				ss << " )";
+				visit_children = false;
+			}
+
+			/// Constant expression replaced by its type
+			void previsit( ConstantExpr* expr ) {
+				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
+				expr->constant.get_type()->accept( tyPrinter );
+				visit_children = false;
+			}
+
+			/// sizeof( ... ), alignof( ... ), offsetof( ... ) replaced by unsigned long constant
+			/// TODO extra expression to resolve argument
+			void previsit( SizeofExpr* ) {
+				ss << (int)BasicType::LongUnsignedInt;
+				visit_children = false;
+			}
+			void previsit( AlignofExpr* ) {
+				ss << (int)BasicType::LongUnsignedInt;
+				visit_children = false;
+			}
+			void previsit( UntypedOffsetofExpr* ) {
+				ss << (int)BasicType::LongUnsignedInt;
+				visit_children = false;
+			}
+
+			/// Logical expressions represented as operators
+			void previsit( LogicalExpr* expr ) {
+				ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
+				expr->arg1->accept( *visitor );
+				ss << ' ';
+				expr->arg2->accept( *visitor );
+				ss << " )";
+				visit_children = false;
+			}
+
+			/// Conditional expression represented as operator
+			void previsit( ConditionalExpr* expr ) {
+				ss << "$if( ";
+				expr->arg1->accept( *visitor );
+				ss << ' ';
+				expr->arg2->accept( *visitor );
+				ss << ' ';
+				expr->arg3->accept( *visitor );
+				ss << " )";
+				visit_children = false;
+			}
+
+			/// Comma expression represented as operator
+			void previsit( CommaExpr* expr ) {
+				ss << "$seq( ";
+				expr->arg1->accept( *visitor );
+				ss << ' ';
+				expr->arg2->accept( *visitor );
+				ss << " )";
+				visit_children = false;
+			}
+
+			// TODO handle ignored ImplicitCopyCtorExpr and below
+		};
+
+		void build( Initializer* init, std::stringstream& ss ) {
+			if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
+				PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
+				si->value->accept( exprPrinter );
+				ss << ' ';
+			} else if ( ListInit* li = dynamic_cast<ListInit*>(init) ) {
+				for ( Initializer* it : li->initializers ) {
+					build( it, ss );
+					ss << ' ';
+				}
+			}
+		}
+
+		/// Adds an object initializer to the list of expressions
+		void build( const std::string& name, Initializer* init, std::stringstream& ss ) {
+			ss << "$constructor( ";
+			rp_name( name, ss );
+			ss << "() ";
+			build( init, ss );
+			ss << ')';
+		}
+
+		/// Adds a return expression to the list of expressions
+		void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
+			ss << "$constructor( ";
+			PassVisitor<TypePrinter> tyPrinter{ closed, ss };
+			rtnType->accept( tyPrinter );
+			ss << ' ';
+			PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
+			expr->accept( exprPrinter );
+			ss << " )";
+		}
+
+		/// Adds all named declarations in a list to the local scope
+		void addAll( const std::list<DeclarationWithType*>& decls ) {
+			for ( auto decl : decls ) {
+				// skip anonymous decls
+				if ( decl->name.empty() ) continue;
+
+				// handle objects
+				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >( decl ) ) {
+					previsit( obj );
+				}
+			}
+		}
+
+		/// encode field access as function
+		void addAggregateFields( AggregateDecl* agg ) {
+			// make field names functions
+			for ( Declaration* member : agg->members ) {
+				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
+					std::stringstream ss;
+					build( obj->name, agg, obj->type, ss );
+					addDecl( ss.str() );
+				}
+			}
+
+			visit_children = false;
+		}
+
+	public:
+		void previsit( ObjectDecl *obj ) {
+			// add variable as declaration
+			std::stringstream ss;
+			build( obj->name, obj->type, ss );
+			addDecl( ss.str() );
+
+			// add initializer as expression if applicable
+			if ( obj->init ) {
+				std::stringstream ss;
+				build( obj->name, obj->init, ss );
+				addExpr( ss.str() );
+			}
+		}
+
+		void previsit( FunctionDecl *decl ) {
+			// skip decls with ftype parameters
+			for ( TypeDecl* tyvar : decl->type->forall ) {
+				if ( tyvar->get_kind() == TypeDecl::Ftype ) {
+					visit_children = false;
+					return;
+				}
+			}
+
+			// add function as declaration
+			std::stringstream ss;
+			build( decl->name, decl->type, ss );
+			addDecl( ss.str() );
+
+			// add body if available
+			if ( decl->statements ) {
+				std::list<Type*> rtns = from_decls( decl->type->returnVals );
+				Type* rtn = nullptr;
+				if ( rtns.size() == 1 ) {
+					if ( ! dynamic_cast<VoidType*>(rtns.front()) ) rtn = rtns.front()->clone();
+				} else if ( rtns.size() > 1 ) {
+					rtn = new TupleType{ Type::Qualifiers{}, rtns };
+				}
+				PassVisitor<ProtoDump> body{ this, rtn };
+
+				for ( TypeDecl* tyvar : decl->type->forall ) {
+					// add set of "closed" types to body so that it can print them as NamedType
+					body.pass.closed.insert( tyvar->name );
+
+					// add assertions to local scope as declarations as well
+					for ( DeclarationWithType* assn : tyvar->assertions ) {
+						assn->accept( body );
+					}
+				}
+				
+				// add named parameters and returns to local scope
+				body.pass.addAll( decl->type->returnVals );
+				body.pass.addAll( decl->type->parameters );
+
+				// add contents of function to new scope
+				decl->statements->accept( body );
+
+				// store sub-scope
+				addSub( std::move(body) );
+			}
+
+			visit_children = false;
+		}
+
+		void previsit( StructDecl* sd ) { addAggregateFields(sd); }
+		void previsit( UnionDecl* ud ) { addAggregateFields(ud); }
+		
+		void previsit( EnumDecl* ed ) {
+			std::unique_ptr<Type> eType = 
+				std::make_unique<BasicType>( Type::Qualifiers{}, BasicType::SignedInt );
+			
+			// add field names directly to enclosing scope
+			for ( Declaration* member : ed->members ) {
+				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
+					previsit(obj);
+				}
+			}
+
+			visit_children = false;
+		}
+
+		void previsit( ReturnStmt* stmt ) {
+			// do nothing for void-returning functions or statements returning nothing
+			if ( ! rtnType || ! stmt->expr ) return;
+
+			// otherwise construct the return type from the expression
+			std::stringstream ss;
+			build( rtnType.get(), stmt->expr, ss );
+			addExpr( ss.str() );
+			visit_children = false;
+		}
+
+		void previsit( Expression* expr ) {
+			std::stringstream ss;
+			PassVisitor<ExprPrinter> exPrinter{ closed, ss };
+			expr->accept( exPrinter );
+			addExpr( ss.str() );
+			visit_children = false;
+		}
+
+		/// Print non-prelude global declarations for resolv proto
+		void printGlobals() const {
+			std::cout << "#ptr<T> $addr T" << std::endl;  // &?
+			int i = (int)BasicType::SignedInt;
+			std::cout << i << " $and " << i << ' ' << i << std::endl;  // ?&&?
+			std::cout << i << " $or " << i << ' ' << i << std::endl;  // ?||?
+			std::cout << "T $if " << i << " T T" << std::endl; // ternary operator
+			std::cout << "T $seq X T" << std::endl;  // ?,?
+		}
+
+	public:
+		/// Prints this ProtoDump instance
+		void print(unsigned indent = 0) const {
+			// print globals at root level
+			if ( ! parent ) printGlobals();
+			// print decls
+			std::string tab( indent, '\t' );
+			for ( const std::string& d : decls ) {
+				std::cout << tab << d << std::endl;
+			}
+			// print divider
+			std::cout << '\n' << tab << "%%\n" << std::endl;
+			// print top-level expressions
+			for ( const std::string& e : exprs ) {
+				std::cout << tab << e << std::endl;
+			}
+			// print child scopes
+			++indent;
+			for ( const PassVisitor<ProtoDump>& s : subs ) {
+				std::cout << tab << '{' << std::endl;
+				s.pass.print( indent );
+				std::cout << tab << '}' << std::endl;
+			}
+		}
+	};
+
+	void dumpAsResolvProto( std::list< Declaration * > &translationUnit ) {
+		PassVisitor<ProtoDump> dump;
+		acceptAll( translationUnit, dump );
+		dump.pass.print();
+	}
+
+}  // namespace CodeTools
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/CodeTools/ResolvProtoDump.h
===================================================================
--- src/CodeTools/ResolvProtoDump.h	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
+++ src/CodeTools/ResolvProtoDump.h	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -0,0 +1,33 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ResolvProtoDump.h -- Translates CFA resolver instances into resolv-proto instances
+//
+// Author           : Aaron Moss
+// Created On       : Tue Sep 11 09:04:00 2018
+// Last Modified By : Aaron Moss
+// Last Modified On : Tue Sep 11 09:04:00 2018
+// Update Count     : 1
+//
+
+#pragma once
+
+#include <list>
+
+class Declaration;
+
+namespace CodeTools {
+
+	/// Prints a translation unit in the input format of the resolv-proto tool
+	void dumpAsResolvProto( std::list< Declaration * > &translationUnit );
+
+}  // namespace CodeTools
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/CodeTools/module.mk
===================================================================
--- src/CodeTools/module.mk	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/CodeTools/module.mk	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -16,3 +16,4 @@
 
 SRC += CodeTools/DeclStats.cc \
+	CodeTools/ResolvProtoDump.cc \
 	CodeTools/TrackLoc.cc
Index: src/CompilationState.cc
===================================================================
--- src/CompilationState.cc	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/CompilationState.cc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -30,4 +30,5 @@
 	parsep = false,
 	resolvep = false,
+	resolvprotop = false,
 	symtabp = false,
 	treep = false,
Index: src/CompilationState.h
===================================================================
--- src/CompilationState.h	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/CompilationState.h	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -31,4 +31,5 @@
 	parsep,
 	resolvep,
+	resolvprotop,
 	symtabp,
 	treep,
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/Makefile.in	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -221,4 +221,5 @@
 	CodeGen/FixNames.$(OBJEXT) CodeGen/FixMain.$(OBJEXT) \
 	CodeGen/OperatorTable.$(OBJEXT) CodeTools/DeclStats.$(OBJEXT) \
+	CodeTools/ResolvProtoDump.$(OBJEXT) \
 	CodeTools/TrackLoc.$(OBJEXT) Concurrency/Keywords.$(OBJEXT) \
 	Concurrency/Waitfor.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
@@ -520,8 +521,9 @@
 	CodeGen/FixNames.cc CodeGen/FixMain.cc \
 	CodeGen/OperatorTable.cc CodeTools/DeclStats.cc \
-	CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
-	Concurrency/Waitfor.cc Common/SemanticError.cc \
-	Common/UniqueName.cc Common/DebugMalloc.cc Common/Assert.cc \
-	Common/Heap.cc Common/Eval.cc ControlStruct/LabelGenerator.cc \
+	CodeTools/ResolvProtoDump.cc CodeTools/TrackLoc.cc \
+	Concurrency/Keywords.cc Concurrency/Waitfor.cc \
+	Common/SemanticError.cc Common/UniqueName.cc \
+	Common/DebugMalloc.cc Common/Assert.cc Common/Heap.cc \
+	Common/Eval.cc ControlStruct/LabelGenerator.cc \
 	ControlStruct/LabelFixer.cc ControlStruct/MLEMutator.cc \
 	ControlStruct/Mutate.cc ControlStruct/ForExprMutator.cc \
@@ -999,4 +1001,6 @@
 CodeTools/DeclStats.$(OBJEXT): CodeTools/$(am__dirstamp) \
 	CodeTools/$(DEPDIR)/$(am__dirstamp)
+CodeTools/ResolvProtoDump.$(OBJEXT): CodeTools/$(am__dirstamp) \
+	CodeTools/$(DEPDIR)/$(am__dirstamp)
 CodeTools/TrackLoc.$(OBJEXT): CodeTools/$(am__dirstamp) \
 	CodeTools/$(DEPDIR)/$(am__dirstamp)
@@ -1101,4 +1105,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/OperatorTable.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/DeclStats.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/ResolvProtoDump.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/TrackLoc.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/Assert.Po@am__quote@
Index: src/Parser/LinkageSpec.cc
===================================================================
--- src/Parser/LinkageSpec.cc	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/Parser/LinkageSpec.cc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 13:22:09 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Jul  7 11:11:00 2017
-// Update Count     : 25
+// Last Modified On : Thr Spt 12 15:59:00 2018
+// Update Count     : 26
 //
 
@@ -23,18 +23,4 @@
 
 namespace LinkageSpec {
-
-Spec linkageCheck( CodeLocation location, const string * spec ) {
-	assert( spec );
-	unique_ptr<const string> guard( spec );	// allocated by lexer
-	if ( *spec == "\"Cforall\"" ) {
-		return Cforall;
-	} else if ( *spec == "\"C\"" ) {
-		return C;
-	} else if ( *spec == "\"BuiltinC\"" ) {
-		return BuiltinC;
-	} else {
-		SemanticError( location, "Invalid linkage specifier " + *spec );
-	} // if
-}
 
 Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
Index: src/Parser/LinkageSpec.h
===================================================================
--- src/Parser/LinkageSpec.h	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/Parser/LinkageSpec.h	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 13:24:28 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jul  2 07:46:49 2018
-// Update Count     : 16
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Spt 13 15:59:00 2018
+// Update Count     : 17
 //
 
@@ -41,6 +41,4 @@
 
 
-	Spec linkageCheck( CodeLocation location, const std::string * );
-	// Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
 	Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
 	/* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ src/main.cc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -34,4 +34,5 @@
 #include "CodeGen/Generate.h"               // for generate
 #include "CodeTools/DeclStats.h"            // for printDeclStats
+#include "CodeTools/ResolvProtoDump.h"      // for dumpAsResolvProto
 #include "CodeTools/TrackLoc.h"             // for fillLocations
 #include "Common/CompilerError.h"           // for CompilerError
@@ -271,4 +272,9 @@
 		CodeTools::fillLocations( translationUnit );
 
+		if ( resolvprotop ) {
+			CodeTools::dumpAsResolvProto( translationUnit );
+			return 0;
+		}
+
 		PASS( "resolve", ResolvExpr::resolve( translationUnit ) );
 		if ( exprp ) {
@@ -376,5 +382,5 @@
 
 void parse_cmdline( int argc, char * argv[], const char *& filename ) {
-	enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, Symbol, Tree, TupleExpansion, Validate, };
+	enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, ResolvProto, Symbol, Tree, TupleExpansion, Validate, };
 
 	static struct option long_opts[] = {
@@ -395,4 +401,5 @@
 		{ "no-prototypes", no_argument, 0, Prototypes },
 		{ "resolver", no_argument, 0, Resolver },
+		{ "resolv-proto", no_argument, 0, ResolvProto },
 		{ "symbol", no_argument, 0, Symbol },
 		{ "tree", no_argument, 0, Tree },
@@ -407,5 +414,5 @@
 	bool Wsuppress = false, Werror = false;
 	int c;
-	while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
+	while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrRstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
 		switch ( c ) {
 		  case Ast:
@@ -479,4 +486,7 @@
 		  case 'r':										// print resolver steps
 			resolvep = true;
+			break;
+			case 'R':										// dump resolv-proto instance
+			resolvprotop = true;
 			break;
 		  case Symbol:
Index: tools/cfa.nanorc
===================================================================
--- tools/cfa.nanorc	(revision 031a88a9185c8893c2e6d735d2cd99e596118b4e)
+++ tools/cfa.nanorc	(revision ec71a50975a9d7697d5de0e27072837d6203d86d)
@@ -2,5 +2,5 @@
 ## WIP
 
-syntax "cfa" "\.cfa"
+syntax "cfa" "\.(c|h)fa"
 
 # Macros
@@ -9,6 +9,6 @@
 # Types
 color green "\<(forall|trait|(o|d|f|t)type|mutex|_Bool|volatile|virtual)\>"
-color green "\<(float|double|bool|char|int|short|long|sizeof|enum|void|auto)\>"
-color green "\<(static|const|struct|union|typedef|extern|(un)?signed|inline)\>"
+color green "\<(float|double|bool|char|int|short|long|enum|void|auto)\>"
+color green "\<(static|const|extern|(un)?signed|inline)\>" "\<(sizeof)\>"
 color green "\<((s?size)|one|zero|((u_?)?int(8|16|32|64|ptr)))_t\>"
 
@@ -19,8 +19,12 @@
 # Control Flow Structures
 color brightyellow "\<(if|else|while|do|for|switch|choose|case|default)\>"
+color brightyellow "\<(disable|enable|waitfor|when|timeout)\>"
 color brightyellow "\<(try|catch(Resume)?|finally)\>"
 
 # Control Flow Statements
 color magenta "\<(goto|return|break|continue|fallthr(u|ough)|throw(Resume)?)\>"
+
+# Escaped Keywords, now Identifiers.
+color white "`\w+`"
 
 # Operator Names
