Index: doc/uC++toCFA/uC++toCFA.tex
===================================================================
--- doc/uC++toCFA/uC++toCFA.tex	(revision bab2917ddf427236b02c457fe13904bbca581868)
+++ doc/uC++toCFA/uC++toCFA.tex	(revision c29807939afb9f148dfc1f67e1395763715b22d4)
@@ -11,6 +11,6 @@
 %% Created On       : Wed Apr  6 14:53:29 2016
 %% Last Modified By : Peter A. Buhr
-%% Last Modified On : Sun Sep 17 09:10:12 2023
-%% Update Count     : 5883
+%% Last Modified On : Sun Oct 15 23:09:58 2023
+%% Update Count     : 5926
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -119,5 +119,5 @@
 
 \title{\vspace*{-0.5in}
-\CC/\uC to \CFA Cheat Sheet}
+\uC to \CFA Cheat Sheet}
 %\author{Peter A. Buhr}
 \date{}
@@ -195,5 +195,30 @@
 \end{cfa}
 \noindent
-In subsequent code examples, the left example is \CC/\uC and the right example is \CFA.
+In subsequent code examples, the left example is \uC and the right example is \CFA.
+
+
+\section{Stream I/O}
+
+\CFA output streams automatically separate values and insert a newline at the end of the print.
+
+\begin{cquote}
+\begin{tabular}{l|l}
+\begin{uC++}
+#include <@iostream@>
+using namespace std;
+int i;   double d;   char c;
+cin >> i >> d >> c;
+cout << i << ' ' << d << ' ' << c | endl;
+\end{uC++}
+&
+\begin{cfa}
+#include <@fstream.hfa@>
+
+int i;   double d;   char c;
+sin | i | d | c;
+sout | i | d | c
+\end{cfa}
+\end{tabular}
+\end{cquote}
 
 
@@ -203,25 +228,53 @@
 \begin{tabular}{l|l}
 \begin{uC++}
-for ( ;; ) { ... } / while ( true ) { ... }
-for ( int i = 0; i < 10; i += 1 ) { ... }
-for ( int i = 5; i < 15; i += 2 ) { ... }
+for ( @;;@ ) { ... }  /  while ( @true@ ) { ... }
+for ( int i = 0; i < @10@; i += 1 ) { ... }
+for ( int i = @5@; i < @15@; i += @2@ ) { ... }
+for ( int i = -1; i <@=@ 10; i += 3 ) { ... }
+for ( int i = 10; i > 0; i @-@= 1 ) { ... }
+\end{uC++}
+&
+\begin{cfa}
+for () { ... }  /  while () { ... }
+for ( @10@ ) { ... }  /  for ( i; @10@ ) { ... }
+for ( i; @5@ ~ @15@ ~ @2@ ) { ... }
+for ( i; -1 ~@=@ 10 ~ 3 ) { ... }
+for ( i; 0 @-@~ 10 ) { ... }
+\end{cfa}
+\\
+\hline
+\begin{uC++}
 int i = 0
 for ( i = 0; i < 10; i += 1 ) { ... }
-if ( i == 10 ) { ... }
-\end{uC++}
-&
-\begin{cfa}
-for () { ... } / while () { ... }
-for ( 10 ) { ... } / for ( i; 10 ) { ... }
-for ( i; 5~15~2 ) { ... }
+@if ( i == 10 )@ { ... }
+\end{uC++}
+&
+\begin{cfa}
 
 for ( i; 10 ) { ... }
-else { ... } // i == 10
-\end{cfa}
-\end{tabular}
-\end{cquote}
-
-
-\section{Exceptions}
+@else@ { ... } // i == 10
+\end{cfa}
+\\
+\hline
+\begin{uC++}
+L1: for ( ;; ) {
+	L2: for ( ;; ) {
+		... @break L1@; ... @break L2@; ...
+	}
+}
+\end{uC++}
+&
+\begin{cfa}
+L1: for () {
+	L2: for () {
+		... @break L1@; ... @break L2@; ...
+	}
+}
+\end{cfa}
+\end{tabular}
+\end{cquote}
+
+
+\section{Exception}
 
 Currently, \CFA uses macros @ExceptionDecl@ and @ExceptionInst@ to declare and instantiate an exception.
@@ -230,13 +283,13 @@
 \begin{uC++}
 
-struct E {		// local or global scope
+@_Exception@ E {	// local or global scope
 	... // exception fields
 };
 try {
 	...
-	if ( ... ) _Resume E( /* initialization */ );
-	if ( ... ) _Throw E( /* initialization */ );
-	...
-} _CatchResume( E & ) { // should be reference
+	if ( ... ) @_Resume@ E( /* initialization */ );
+	if ( ... ) @_Throw@ E( /* initialization */ );
+		...
+} @_CatchResume@( E & ) { // should be reference
 	...
 } catch( E & ) {
@@ -252,8 +305,8 @@
 try {
 	...
-	if ( ... ) throwResume @ExceptionInst@( E, /* intialization */ );
-	if ( ... ) throw @ExceptionInst@( E, /* intialization */ );
+	if ( ... ) @throwResume@ @ExceptionInst@( E, /* intialization */ );
+	if ( ... ) @throw@ @ExceptionInst@( E, /* intialization */ );
 	...
-} catchResume( E * ) { // must be pointer
+} @catchResume@( E * ) { // must be pointer
 	...
 } catch( E * ) {
@@ -265,24 +318,61 @@
 
 
-\section{Stream I/O}
-
-\CFA output streams automatically separate values and insert a newline at the end of the print.
+\section{Non-local Exception}
+
+\begin{cquote}
+\begin{tabular}{l|ll}
+\begin{uC++}
+
+
+void main() {
+	try {
+		_Enable {
+			... suspend(); ...
+		}
+	} @_CatchResume@( E & ) { // reference
+		...
+	} catch( E & ) {
+		...
+	}
+}
+\end{uC++}
+&
+\begin{cfa}
+#define resumePoll( coroutine ) resume( coroutine ); checked_poll()
+#define suspendPoll suspend; checked_poll()
+void main() {
+	try {
+		enable_ehm();
+		... suspendPoll ...
+		disable_ehm();
+	} @catchResume@( E * ) { // pointer
+		...
+	} catch( E & ) {
+		...
+	}
+}
+\end{cfa}
+\end{tabular}
+\end{cquote}
+
+
+\section{Constructor / Destructor}
 
 \begin{cquote}
 \begin{tabular}{l|l}
 \begin{uC++}
-#include <@iostream@>
-using namespace std;
-int i;   double d;   char c;
-cin >> i >> d >> c;
-cout << i << ' ' << d << ' ' << c | endl;
-\end{uC++}
-&
-\begin{cfa}
-#include <@fstream.hfa@>
-
-int i;   double d;   char c;
-sin | i | d | c;
-sout | i | d | c
+struct S {
+	... // fields
+	@S@(...) { ... }
+	@~S@(...) { ... }
+};
+\end{uC++}
+&
+\begin{cfa}
+struct S {
+	... // fields
+};
+@?{}@( @S & s,@ ...) { ... }
+@^?{}@( @S & s@ ) { ... }
 \end{cfa}
 \end{tabular}
@@ -332,27 +422,4 @@
 
 
-\section{Constructor / Destructor}
-
-\begin{cquote}
-\begin{tabular}{l|l}
-\begin{uC++}
-struct S {
-	... // fields
-	@S@(...) { ... }
-	@~S@(...) { ... }
-};
-\end{uC++}
-&
-\begin{cfa}
-struct S {
-	... // fields
-};
-@?{}@( @S & s,@ ...) { ... }
-@^?{}@( @S & s@ ) { ... }
-\end{cfa}
-\end{tabular}
-\end{cquote}
-
-
 \section{\texorpdfstring{Structures (object-oriented \protect\vs routine style)}{Structures (object-oriented vs. routine style)}}
 
Index: src/GenPoly/BoxNew.cpp
===================================================================
--- src/GenPoly/BoxNew.cpp	(revision bab2917ddf427236b02c457fe13904bbca581868)
+++ src/GenPoly/BoxNew.cpp	(revision c29807939afb9f148dfc1f67e1395763715b22d4)
@@ -386,16 +386,8 @@
 	// return value.
 
-	/// Pass the extra type parameters from polymorphic generic arguments or
-	/// return types into a function application.
-	ast::vector<ast::Expr>::iterator passArgTypeVars(
-		ast::ApplicationExpr * expr, ast::Type const * parmType,
-		ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg,
-		const TypeVarMap & exprTyVars, std::set<std::string> & seenTypes );
-	/// Passes extra type parameters into a polymorphic function application.
+	/// Passes extra layout arguments for sized polymorphic type parameters.
 	ast::vector<ast::Expr>::iterator passTypeVars(
 		ast::ApplicationExpr * expr,
-		ast::Type const * polyRetType,
-		ast::FunctionType const * funcType,
-		const TypeVarMap & exprTyVars );
+		ast::FunctionType const * funcType );
 	/// Wraps a function application with a new temporary for the
 	/// out-parameter return value.
@@ -700,5 +692,5 @@
 	// the concrete type's parameters, not the formal type's).
 	ast::vector<ast::Expr>::iterator argIt =
-		passTypeVars( mutExpr, concRetType, function, exprTypeVars );
+		passTypeVars( mutExpr, function );
 	addInferredParams( mutExpr, argIt, function, exprTypeVars );
 
@@ -812,54 +804,7 @@
 }
 
-// arg is an in/out parameter that matches the return value.
-ast::vector<ast::Expr>::iterator CallAdapter::passArgTypeVars(
-		ast::ApplicationExpr * expr, ast::Type const * paramType,
-		ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg,
-		const TypeVarMap & exprTypeVars, std::set<std::string> & seenTypes ) {
-	ast::Type const * polyType = isPolyType( paramType, exprTypeVars );
-	if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {
-		return arg;
-	}
-
-	std::string typeName = Mangle::mangleType( polyType );
-	if ( seenTypes.count( typeName ) ) return arg;
-
-	arg = expr->args.insert( arg,
-		new ast::SizeofExpr( expr->location, ast::deepCopy( argBaseType ) )
-	);
-	arg++;
-	arg = expr->args.insert( arg,
-		new ast::AlignofExpr( expr->location, ast::deepCopy( argBaseType ) )
-	);
-	arg++;
-	if ( dynamic_cast<ast::StructInstType const *>( polyType ) ) {
-		auto argBaseStructType =
-				dynamic_cast<ast::StructInstType const *>( argBaseType );
-		if ( nullptr == argBaseStructType ) {
-			SemanticError( expr,
-				"Cannot pass non-structure type for generic struct: " );
-		}
-
-		// Zero-length arrays are forbidden by C, so don't pass
-		// offset for empty structure.
-		if ( !argBaseStructType->base->members.empty() ) {
-			arg = expr->args.insert( arg,
-				new ast::OffsetPackExpr(
-					expr->location,
-					ast::deepCopy( argBaseStructType ) )
-			);
-			arg++;
-		}
-	}
-
-	seenTypes.insert( typeName );
-	return arg;
-}
-
 ast::vector<ast::Expr>::iterator CallAdapter::passTypeVars(
 		ast::ApplicationExpr * expr,
-		ast::Type const * polyRetType,
-		ast::FunctionType const * function,
-		const TypeVarMap & exprTypeVars ) {
+		ast::FunctionType const * function ) {
 	assert( typeSubs );
 	ast::vector<ast::Expr>::iterator arg = expr->args.begin();
@@ -880,46 +825,4 @@
 			new ast::AlignofExpr( expr->location, ast::deepCopy( concrete ) ) );
 		arg++;
-	}
-
-	// Add size/align for generic types to parameter list.
-	if ( !expr->func->result ) return arg;
-	ast::FunctionType const * funcType = getFunctionType( expr->func->result );
-	assert( funcType );
-
-	// This iterator points at first original argument.
-	ast::vector<ast::Expr>::const_iterator funcArg;
-	// Names for generic types we've seen.
-	std::set<std::string> seenTypes;
-
-	// A polymorphic return type may need to be added to the argument list.
-	if ( polyRetType ) {
-		assert( typeSubs );
-		auto concRetType = replaceWithConcrete( polyRetType, *typeSubs );
-		// TODO: This write-back may not be correct.
-		arg = passArgTypeVars( expr, polyRetType, concRetType,
-				arg, exprTypeVars, seenTypes );
-		// Skip the return parameter in the argument list.
-		funcArg = arg + 1;
-	} else {
-		funcArg = arg;
-	}
-
-	// TODO:
-	// I believe this is (starts as) the number of original arguments to the
-	// function with the args before funcArg all being inserted.
-	ptrdiff_t argsToPass = std::distance( funcArg, expr->args.cend() );
-
-	// Add type information args for presently unseen types in parameter list.
-	ast::vector<ast::Type>::const_iterator funcParam = funcType->params.begin();
-	// assert( funcType->params.size() == argsToPass );
-	for ( ; funcParam != funcType->params.end() && 0 < argsToPass
-			; ++funcParam, --argsToPass ) {
-		assert( 0 < argsToPass );
-		assert( argsToPass <= (ptrdiff_t)expr->args.size() );
-		ptrdiff_t index = expr->args.size() - argsToPass;
-		ast::Type const * argType = expr->args[index]->result;
-		if ( nullptr == argType ) continue;
-		arg = passArgTypeVars( expr, *funcParam, argType,
-				arg, exprTypeVars, seenTypes );
 	}
 	return arg;
@@ -1523,11 +1426,4 @@
 }
 
-ast::ObjectDecl * makePtr(
-		CodeLocation const & location, std::string const & name ) {
-	return new ast::ObjectDecl( location, name,
-		new ast::PointerType( makeSizeAlignType() ),
-		nullptr, ast::Storage::Classes(), ast::Linkage::C, nullptr );
-}
-
 ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) {
 	TypeVarMap localTypeVars = { ast::TypeData() };
@@ -1584,36 +1480,7 @@
 	mutDecl->assertions.clear();
 
-	// Add size/align for generic parameter types to parameter list.
-	std::set<std::string> seenTypes;
-	ast::vector<ast::DeclWithType> otypeParams;
-	for ( ast::ptr<ast::DeclWithType> & funcParam : mutDecl->params ) {
-		ast::Type const * polyType = isPolyType( funcParam->get_type(), localTypeVars );
-		if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {
-			continue;
-		}
-		std::string typeName = Mangle::mangleType( polyType );
-		if ( seenTypes.count( typeName ) ) continue;
-		seenTypes.insert( typeName );
-
-		auto sizeParam = makeObj( funcParam->location, sizeofName( typeName ) );
-		otypeParams.emplace_back( sizeParam );
-
-		auto alignParam = makeObj( funcParam->location, alignofName( typeName ) );
-		otypeParams.emplace_back( alignParam );
-
-		// Zero-length arrays are illegal in C, so empty structs have no
-		// offset array.
-		if ( auto * polyStruct =
-				dynamic_cast<ast::StructInstType const *>( polyType ) ;
-				polyStruct && !polyStruct->base->members.empty() ) {
-			auto offsetParam = makePtr( funcParam->location, offsetofName( typeName ) );
-			otypeParams.emplace_back( offsetParam );
-		}
-	}
-
 	// Prepend each argument group. From last group to first. addAdapters
 	// does do the same, it just does it itself and see all other parameters.
 	spliceBegin( mutDecl->params, inferredParams );
-	spliceBegin( mutDecl->params, otypeParams );
 	spliceBegin( mutDecl->params, layoutParams );
 	addAdapters( mutDecl, localTypeVars );
@@ -1815,13 +1682,4 @@
 	beginGenericScope();
 	beginTypeScope( decl->type );
-
-	// TODO: Going though dec->params does not work for some reason.
-	for ( ast::ptr<ast::Type> const & funcParam : decl->type->params ) {
-		// Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`
-		ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );
-		if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {
-			knownLayouts.insert( Mangle::mangleType( polyType ) );
-		}
-	}
 }
 
@@ -1898,14 +1756,4 @@
 	// don't mark them as known in this scope.
 	expect_func_type = false;
-
-	// Make sure that any type information passed into the function is
-	// accounted for.
-	for ( ast::ptr<ast::Type> const & funcParam : type->params ) {
-		// Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`
-		ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );
-		if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {
-			knownLayouts.insert( Mangle::mangleType( polyType ) );
-		}
-	}
 }
 
