Index: src/CodeTools/ResolvProtoDump.cc
===================================================================
--- src/CodeTools/ResolvProtoDump.cc	(revision 40cd873d81d1e7979f1ab87d5c95a9cb89059a09)
+++ src/CodeTools/ResolvProtoDump.cc	(revision 4d59ff978914cacb46b235486a041b512eeab5c6)
@@ -27,7 +27,9 @@
 
 #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"
@@ -41,11 +43,31 @@
 		std::vector<ProtoDump> subs;     ///< Sub-scopes
 		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) {}
+		ProtoDump() : decls(), exprs(), subs(), parent(nullptr), rtnType(nullptr) {}
 
 		/// Child constructor
-		ProtoDump(const ProtoDump* p) : decls(), exprs(), subs(), parent(p) {}
+		ProtoDump(const ProtoDump* p, Type* r) : decls(), exprs(), subs(), parent(p), rtnType(r) {}
+
+		// Fix copy issues
+		ProtoDump( const ProtoDump& o ) 
+			: decls(o.decls), exprs(o.exprs), subs(o.subs), 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;
+			parent = o.parent;
+			rtnType.reset( maybeClone(o.rtnType.get()) );
+			
+			return *this;
+		}
+		ProtoDump& operator= ( ProtoDump&& ) = default;
 
 	private:
@@ -474,4 +496,37 @@
 		};
 
+		void build( Initializer* init, std::stringstream& ss ) {
+			if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
+				PassVisitor<ExprPrinter> exprPrinter{ 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{ ss };
+			rtnType->accept( tyPrinter );
+			ss << ' ';
+			PassVisitor<ExprPrinter> exprPrinter{ ss };
+			expr->accept( exprPrinter );
+			ss << " )";
+		}
+
 		/// Adds all named declarations in a list to the local scope
 		void addAll( const std::list<DeclarationWithType*>& decls ) {
@@ -507,4 +562,11 @@
 			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() );
+			}
 		}
 
@@ -517,5 +579,12 @@
 			// add body if available
 			if ( decl->statements ) {
-				PassVisitor<ProtoDump> body{ this };
+				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 };
 				
 				// add named parameters and returns to local scope
@@ -554,4 +623,15 @@
 		}
 
+		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;
@@ -571,5 +651,5 @@
 			}
 			// print divider
-			std::cout << tab << "%%" << std::endl;
+			std::cout << '\n' << tab << "%%\n" << std::endl;
 			// print top-level expressions
 			for ( const std::string& e : exprs ) {
