Index: src/CodeTools/ResolvProtoDump.cc
===================================================================
--- src/CodeTools/ResolvProtoDump.cc	(revision 4d59ff978914cacb46b235486a041b512eeab5c6)
+++ src/CodeTools/ResolvProtoDump.cc	(revision a4a000d2a3ff4a2bfd24720b9abb1a16354d6a09)
@@ -39,24 +39,26 @@
 	/// 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
-		const ProtoDump* parent;         ///< Outer lexical scope
-		std::unique_ptr<Type> rtnType;   ///< Return type for this scope
+		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(), parent(nullptr), rtnType(nullptr) {}
+		ProtoDump() : decls(), exprs(), subs(), closed(), parent(nullptr), rtnType(nullptr) {}
 
 		/// Child constructor
-		ProtoDump(const ProtoDump* p, Type* r) : decls(), exprs(), subs(), parent(p), rtnType(r) {}
+		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), parent(o.parent), 
+		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 ) {
+		ProtoDump& operator= (const ProtoDump& o) {
 			if ( this == &o ) return *this;
 
@@ -64,4 +66,5 @@
 			exprs = o.exprs;
 			subs = o.subs;
+			closed = o.closed;
 			parent = o.parent;
 			rtnType.reset( maybeClone(o.rtnType.get()) );
@@ -69,5 +72,5 @@
 			return *this;
 		}
-		ProtoDump& operator= ( ProtoDump&& ) = default;
+		ProtoDump& operator= (ProtoDump&&) = default;
 
 	private:
@@ -205,8 +208,10 @@
 		/// Visitor for printing types
 		struct TypePrinter : public WithShortCircuiting, WithVisitorRef<TypePrinter>, WithGuards {
-			std::stringstream& ss;  ///< Output to print to
-			unsigned depth;         ///< Depth of nesting from root type
-
-			TypePrinter( std::stringstream& ss ) : ss(ss), depth(0) {}
+			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
@@ -274,7 +279,9 @@
 			void previsit( EnumInstType* ) { ss << (int)BasicType::SignedInt; }
 
-			// make sure first letter of TypeInstType is capitalized
 			void previsit( TypeInstType* vt ) {
-				ti_name( vt->name, ss );
+				// 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 ); }
 			}
 
@@ -302,9 +309,18 @@
 		/// builds description of function
 		void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
-			PassVisitor<TypePrinter> printTy{ 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 );
-			// TODO handle assertions
+			// print assertions
+			for ( TypeDecl* tyvar : fnTy->forall ) {
+				for ( DeclarationWithType* assn : tyvar->assertions ) {
+					ss << " | "; 
+					build( assn->name, assn->get_type(), ss );
+				}
+			}
 		}
 
@@ -326,5 +342,5 @@
 
 			// print variable declaration as zero-arg function
-			PassVisitor<TypePrinter> printTy{ ss };
+			PassVisitor<TypePrinter> printTy{ closed, ss };
 			norefs->accept( printTy );
 			ss << ' ';
@@ -338,5 +354,5 @@
 
 			// print access as new field name
-			PassVisitor<TypePrinter> printTy{ ss };
+			PassVisitor<TypePrinter> printTy{ closed, ss };
 			norefs->accept( printTy );
 			ss << ' ';
@@ -359,8 +375,9 @@
 		struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
 			// TODO change interface to generate multiple expression candidates
-
-			std::stringstream& ss;  ///< Output to print to
-
-			ExprPrinter( std::stringstream& ss ) : ss(ss) {}
+			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 nullary function calls
@@ -401,5 +418,4 @@
 			/// Address-of handled as operator
 			void previsit( AddressExpr* expr ) {
-				// TODO global function to implement this
 				ss << "$addr( ";
 				expr->arg->accept( *visitor );
@@ -411,5 +427,5 @@
 			/// TODO put cast target functions in, and add second expression for target
 			void previsit( CastExpr* cast ) {
-				PassVisitor<TypePrinter> tyPrinter{ ss };
+				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
 				cast->result->accept( tyPrinter );
 				visit_children = false;
@@ -438,5 +454,5 @@
 			/// Constant expression replaced by its type
 			void previsit( ConstantExpr* expr ) {
-				PassVisitor<TypePrinter> tyPrinter{ ss };
+				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
 				expr->constant.get_type()->accept( tyPrinter );
 				visit_children = false;
@@ -460,5 +476,4 @@
 			/// Logical expressions represented as operators
 			void previsit( LogicalExpr* expr ) {
-				// TODO global functions for these
 				ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
 				expr->arg1->accept( *visitor );
@@ -471,5 +486,4 @@
 			/// Conditional expression represented as operator
 			void previsit( ConditionalExpr* expr ) {
-				// TODO global function for this
 				ss << "$if( ";
 				expr->arg1->accept( *visitor );
@@ -484,5 +498,4 @@
 			/// Comma expression represented as operator
 			void previsit( CommaExpr* expr ) {
-				// TODO global function for this
 				ss << "$seq( ";
 				expr->arg1->accept( *visitor );
@@ -498,5 +511,5 @@
 		void build( Initializer* init, std::stringstream& ss ) {
 			if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
-				PassVisitor<ExprPrinter> exprPrinter{ ss };
+				PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
 				si->value->accept( exprPrinter );
 				ss << ' ';
@@ -521,8 +534,8 @@
 		void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
 			ss << "$constructor( ";
-			PassVisitor<TypePrinter> tyPrinter{ ss };
+			PassVisitor<TypePrinter> tyPrinter{ closed, ss };
 			rtnType->accept( tyPrinter );
 			ss << ' ';
-			PassVisitor<ExprPrinter> exprPrinter{ ss };
+			PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
 			expr->accept( exprPrinter );
 			ss << " )";
@@ -587,12 +600,18 @@
 				}
 				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 );
-				
-				// TODO add assertions to local scope
-
-				// TODO add set of "closed" types to body so that it can print them as NamedType
 
 				// add contents of function to new scope
@@ -636,5 +655,5 @@
 		void previsit( Expression* expr ) {
 			std::stringstream ss;
-			PassVisitor<ExprPrinter> exPrinter{ss};
+			PassVisitor<ExprPrinter> exPrinter{ closed, ss };
 			expr->accept( exPrinter );
 			addExpr( ss.str() );
@@ -642,9 +661,21 @@
 		}
 
+		/// 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' );
-			// print decls
 			for ( const std::string& d : decls ) {
 				std::cout << tab << d << std::endl;
