Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/AST/Convert.cpp	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -265,4 +265,5 @@
 		stmt->location = node->location;
 		stmt->labels = makeLabelL( stmt, node->labels );
+		cache.emplace( node, stmt );
 		this->node = stmt;
 		return nullptr;
@@ -270,4 +271,5 @@
 
 	const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
 		stmtPostamble( stmt, node );
@@ -276,4 +278,5 @@
 
 	const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new ExprStmt( get<Expression>().accept1( node->expr ) );
 		return stmtPostamble( stmt, node );
@@ -281,4 +284,5 @@
 
 	const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new AsmStmt(
 			node->isVolatile,
@@ -293,4 +297,5 @@
 
 	const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new DirectiveStmt( node->directive );
 		return stmtPostamble( stmt, node );
@@ -298,4 +303,5 @@
 
 	const ast::Stmt * visit( const ast::IfStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new IfStmt(
 			get<Expression>().accept1( node->cond ),
@@ -308,4 +314,5 @@
 
 	const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new SwitchStmt(
 			get<Expression>().accept1( node->cond ),
@@ -316,4 +323,5 @@
 
 	const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new CaseStmt(
 			get<Expression>().accept1( node->cond ),
@@ -325,4 +333,5 @@
 
 	const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto inits = get<Statement>().acceptL( node->inits );
 		auto stmt = new WhileStmt(
@@ -336,4 +345,5 @@
 
 	const ast::Stmt * visit( const ast::ForStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new ForStmt(
 			get<Statement>().acceptL( node->inits ),
@@ -346,4 +356,5 @@
 
 	const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		BranchStmt * stmt;
 		if (node->computedTarget) {
@@ -375,4 +386,5 @@
 
 	const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
 		return stmtPostamble( stmt, node );
@@ -380,4 +392,5 @@
 
 	const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		ThrowStmt::Kind kind;
 		switch (node->kind) {
@@ -400,4 +413,5 @@
 
 	const ast::Stmt * visit( const ast::TryStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto handlers = get<CatchStmt>().acceptL( node->handlers );
 		auto stmt = new TryStmt(
@@ -410,4 +424,5 @@
 
 	const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		CatchStmt::Kind kind;
 		switch (node->kind) {
@@ -431,4 +446,5 @@
 
 	const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
 		return stmtPostamble( stmt, node );
@@ -436,4 +452,5 @@
 
 	const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new WaitForStmt;
 		stmt->clauses.reserve( node->clauses.size() );
@@ -460,4 +477,5 @@
 
 	const ast::Stmt * visit( const ast::WithStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new WithStmt(
 			get<Expression>().acceptL( node->exprs ),
@@ -468,4 +486,5 @@
 
 	const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new NullStmt();
 		stmtPostamble( stmt, node );
@@ -474,4 +493,5 @@
 
 	const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
+		if ( inCache( node ) ) return nullptr;
 		auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
 		return stmtPostamble( stmt, node );
@@ -479,6 +499,9 @@
 
 	const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
-		(void)node;
-		return nullptr;
+		if ( inCache( node ) ) return nullptr;
+		auto stmt = new ImplicitCtorDtorStmt{
+			get<Statement>().accept1( node->callStmt )
+		};
+		return stmtPostamble( stmt, node );
 	}
 
@@ -525,15 +548,18 @@
 	}
 
+	Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
+
+		tgt->location  = src->location;
+		tgt->env       = convertTypeSubstitution(src->env);
+		tgt->extension = src->extension;
+
+		convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
+		return tgt;
+	}
+
 	Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
 
-		tgt->location = src->location;
-
 		tgt->result = get<Type>().accept1(src->result);
-		tgt->env    = convertTypeSubstitution(src->env);
-
-		tgt->extension = src->extension;
-		convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
-
-		return tgt;
+		return visitBaseExpr_skipResultType(src, tgt);
 	}
 
@@ -628,8 +654,8 @@
 
 	const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
+		auto expr = visitBaseExpr_skipResultType( node,
 			new VirtualCastExpr(
 				get<Expression>().accept1(node->arg),
-				nullptr // cast's "to" type is expr's result type; converted in visitBaseExpr
+				get<Type>().accept1(node->result)
 			)
 		);
@@ -849,85 +875,205 @@
 
 	const ast::Expr * visit( const ast::TypeExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new TypeExpr(
+				get<Type>().accept1(node->type)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::AsmExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new AsmExpr(
+				get<Expression>().accept1(node->inout),
+				get<Expression>().accept1(node->constraint),
+				get<Expression>().accept1(node->operand)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
-		(void)node;
+		auto rslt = new ImplicitCopyCtorExpr(
+			get<ApplicationExpr>().accept1(node->callExpr)
+		);
+
+		rslt->tempDecls = get<ObjectDecl>().acceptL(node->tempDecls);
+		rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
+		rslt->dtors = get<Expression>().acceptL(node->dtors);
+
+		auto expr = visitBaseExpr( node, rslt );
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new ConstructorExpr(
+				get<Expression>().accept1(node->callExpr)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr_skipResultType( node,
+			new CompoundLiteralExpr(
+				get<Type>().accept1(node->result),
+				get<Initializer>().accept1(node->init)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::RangeExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new RangeExpr(
+				get<Expression>().accept1(node->low),
+				get<Expression>().accept1(node->high)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new UntypedTupleExpr(
+				get<Expression>().acceptL(node->exprs)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::TupleExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new UntypedTupleExpr(
+				get<Expression>().acceptL(node->exprs)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new TupleIndexExpr(
+				get<Expression>().accept1(node->tuple),
+				node->index
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new TupleAssignExpr(
+				get<StmtExpr>().accept1(node->stmtExpr)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::StmtExpr * node ) override final {
-		(void)node;
+		auto rslt = new StmtExpr(
+			get<CompoundStmt>().accept1(node->stmts)
+		);
+
+		rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
+		rslt->dtors       = get<Expression>().acceptL(node->dtors);
+
+		auto expr = visitBaseExpr( node, rslt );
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
-		(void)node;
+		auto rslt = new UniqueExpr(
+			get<Expression>().accept1(node->expr)
+		);
+
+		rslt->object = get<ObjectDecl>  ().accept1(node->object);
+		rslt->var    = get<VariableExpr>().accept1(node->var);
+
+		auto expr = visitBaseExpr( node, rslt );
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
-		(void)node;
+		std::list<InitAlternative> initAlts;
+		for (auto ia : node->initAlts) {
+			initAlts.push_back(InitAlternative(
+				get<Type>       ().accept1(ia.type),
+				get<Designation>().accept1(ia.designation)
+			));
+		}
+		auto expr = visitBaseExpr( node,
+			new UntypedInitExpr(
+				get<Expression>().accept1(node->expr),
+				initAlts
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::InitExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new InitExpr(
+				get<Expression>().accept1(node->expr),
+				get<Designation>().accept1(node->designation)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new DeletedExpr(
+				get<Expression>().accept1(node->expr),
+				inCache(node->deleteStmt) ?
+					this->node :
+					get<BaseSyntaxNode>().accept1(node->deleteStmt)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new DefaultArgExpr(
+				get<Expression>().accept1(node->expr)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::GenericExpr * node ) override final {
-		(void)node;
+		std::list<GenericExpr::Association> associations;
+		for (auto association : node->associations) {
+			associations.push_back(GenericExpr::Association(
+				get<Type>      ().accept1(association.type),
+				get<Expression>().accept1(association.expr)
+			));
+		}
+		auto expr = visitBaseExpr( node,
+			new GenericExpr(
+				get<Expression>().accept1(node->control),
+				associations
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
@@ -1141,30 +1287,55 @@
 
 	const ast::Designation * visit( const ast::Designation * node ) override final {
-		(void)node;
+		auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
+		designation->location = node->location;
+		this->node = designation;
 		return nullptr;
 	}
 
 	const ast::Init * visit( const ast::SingleInit * node ) override final {
-		(void)node;
+		auto init = new SingleInit(
+			get<Expression>().accept1( node->value ),
+			ast::MaybeConstruct == node->maybeConstructed
+		);
+		init->location = node->location;
+		this->node = init;
 		return nullptr;
 	}
 
 	const ast::Init * visit( const ast::ListInit * node ) override final {
-		(void)node;
+		auto init = new ListInit(
+			get<Initializer>().acceptL( node->initializers ),
+			get<Designation>().acceptL( node->designations ),
+			ast::MaybeConstruct == node->maybeConstructed
+		);
+		init->location = node->location;
+		this->node = init;
 		return nullptr;
 	}
 
 	const ast::Init * visit( const ast::ConstructorInit * node ) override final {
-		(void)node;
+		auto init = new ConstructorInit(
+			get<Statement>().accept1( node->ctor ),
+			get<Statement>().accept1( node->dtor ),
+			get<Initializer>().accept1( node->init )
+		);
+		init->location = node->location;
+		this->node = init;
 		return nullptr;
 	}
 
 	const ast::Attribute * visit( const ast::Attribute * node ) override final {
-		(void)node;
+		auto attr = new Attribute(
+			node->name,
+			get<Expression>().acceptL(node->parameters)
+		);
+		this->node = attr;
 		return nullptr;
 	}
 
 	const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
-		(void)node;
+		// Handled by convertTypeSubstitution helper instead.
+		// TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
+		assert( 0 );
 		return nullptr;
 	}
@@ -1277,7 +1448,22 @@
 	virtual void visit( FunctionDecl * old ) override final {
 		if ( inCache( old ) ) return;
-		// TODO
-		auto decl = (ast::FunctionDecl *)nullptr;
+		auto decl = new ast::FunctionDecl{
+			old->location,
+			old->name,
+			GET_ACCEPT_1(type, FunctionType),
+			GET_ACCEPT_1(statements, CompoundStmt),
+			{ old->storageClasses.val },
+			{ old->linkage.val },
+			GET_ACCEPT_V(attributes, Attribute),
+			{ old->get_funcSpec().val }
+		};
+		decl->scopeLevel = old->scopeLevel;
+		decl->mangleName = old->mangleName;
+		decl->isDeleted  = old->isDeleted;
+		decl->uniqueId   = old->uniqueId;
+		decl->extension  = old->extension;
 		cache.emplace( old, decl );
+
+		this->node = decl;
 	}
 
@@ -1364,8 +1550,21 @@
 
 	virtual void visit( TypeDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		// TODO
-		auto decl = (ast::TypeDecl *)nullptr;
+		if ( inCache( old ) ) return;	
+		auto decl = new ast::TypeDecl{
+			old->location,
+			old->name,
+			{ old->storageClasses.val },
+			GET_ACCEPT_1(base, Type),
+			(ast::TypeVar::Kind)(unsigned)old->kind,
+			old->sized,
+			GET_ACCEPT_1(init, Type)
+		};
+		decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
+		decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
 		cache.emplace( old, decl );
+
+		this->node = decl;
 	}
 
@@ -1387,13 +1586,31 @@
 	}
 
-	virtual void visit( AsmDecl * ) override final {
-
-	}
-
-	virtual void visit( StaticAssertDecl * ) override final {
-
+	virtual void visit( AsmDecl * old ) override final {
+		auto decl = new ast::AsmDecl{
+			old->location, 
+			GET_ACCEPT_1(stmt, AsmStmt)
+		};
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( StaticAssertDecl * old ) override final {
+		auto decl = new ast::StaticAssertDecl{
+			old->location,
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_1(message, ConstantExpr)
+		};
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
 	}
 
 	virtual void visit( CompoundStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		auto stmt = new ast::CompoundStmt(
 			old->location,
@@ -1403,7 +1620,9 @@
 
 		this->node = stmt;
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( ExprStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::ExprStmt(
 			old->location,
@@ -1411,7 +1630,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( AsmStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::AsmStmt(
 			old->location,
@@ -1424,7 +1645,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( DirectiveStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::DirectiveStmt(
 			old->location,
@@ -1432,7 +1655,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( IfStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::IfStmt(
 			old->location,
@@ -1443,7 +1668,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( SwitchStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::SwitchStmt(
 			old->location,
@@ -1452,7 +1679,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( CaseStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::CaseStmt(
 			old->location,
@@ -1461,7 +1690,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( WhileStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::WhileStmt(
 			old->location,
@@ -1472,7 +1703,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( ForStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::ForStmt(
 			old->location,
@@ -1483,7 +1716,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( BranchStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		if (old->computedTarget) {
 			this->node = new ast::BranchStmt(
@@ -1519,7 +1754,9 @@
 			this->node = stmt;
 		}
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( ReturnStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::ReturnStmt(
 			old->location,
@@ -1527,7 +1764,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( ThrowStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		ast::ThrowStmt::Kind kind;
 		switch (old->kind) {
@@ -1549,7 +1788,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( TryStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::TryStmt(
 			old->location,
@@ -1559,7 +1800,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( CatchStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		ast::CatchStmt::Kind kind;
 		switch (old->kind) {
@@ -1582,7 +1825,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( FinallyStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::FinallyStmt(
 			old->location,
@@ -1590,7 +1835,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( WaitForStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		ast::WaitForStmt * stmt = new ast::WaitForStmt(
 			old->location,
@@ -1620,7 +1867,9 @@
 
 		this->node = stmt;
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( WithStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::WithStmt(
 			old->location,
@@ -1629,14 +1878,18 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( NullStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::NullStmt(
 			old->location,
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( DeclStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::DeclStmt(
 			old->location,
@@ -1644,7 +1897,9 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
 	virtual void visit( ImplicitCtorDtorStmt * old ) override final {
+		if ( inCache( old ) ) return;
 		this->node = new ast::ImplicitCtorDtorStmt(
 			old->location,
@@ -1652,4 +1907,5 @@
 			GET_LABELS_V(old->labels)
 		);
+		cache.emplace( old, this->node );
 	}
 
@@ -1696,7 +1952,6 @@
 	}
 
-	ast::Expr * visitBaseExpr(Expression * old, ast::Expr * nw) {
-
-		nw->result = GET_ACCEPT_1(result, Type);
+	ast::Expr * visitBaseExpr_SkipResultType(Expression * old, ast::Expr * nw) {
+
 		nw->env    = convertTypeSubstitution(old->env);
 
@@ -1705,4 +1960,10 @@
 
 		return nw;
+	}
+
+	ast::Expr * visitBaseExpr(Expression * old, ast::Expr * nw) {
+
+		nw->result = GET_ACCEPT_1(result, Type);
+		return visitBaseExpr_SkipResultType(old, nw);;
 	}
 
@@ -1772,9 +2033,9 @@
 
 	virtual void visit( VirtualCastExpr * old ) override final {
-		this->node = visitBaseExpr( old,
+		this->node = visitBaseExpr_SkipResultType( old,
 			new ast::VirtualCastExpr(
 				old->location,
 				GET_ACCEPT_1(arg, Expr),
-				nullptr // cast's "to" type is expr's result type; converted in visitBaseExpr
+				GET_ACCEPT_1(result, Type)
 			)
 		);
@@ -2001,70 +2262,189 @@
 	}
 
-	virtual void visit( TypeExpr * ) override final {
-
-	}
-
-	virtual void visit( AsmExpr * ) override final {
-
-	}
-
-	virtual void visit( ImplicitCopyCtorExpr * ) override final {
-
-	}
-
-	virtual void visit( ConstructorExpr *  ) override final {
-
-	}
-
-	virtual void visit( CompoundLiteralExpr * ) override final {
-
-	}
-
-	virtual void visit( RangeExpr * ) override final {
-
-	}
-
-	virtual void visit( UntypedTupleExpr * ) override final {
-
-	}
-
-	virtual void visit( TupleExpr * ) override final {
-
-	}
-
-	virtual void visit( TupleIndexExpr * ) override final {
-
-	}
-
-	virtual void visit( TupleAssignExpr * ) override final {
-
-	}
-
-	virtual void visit( StmtExpr *  ) override final {
-
-	}
-
-	virtual void visit( UniqueExpr *  ) override final {
-
-	}
-
-	virtual void visit( UntypedInitExpr *  ) override final {
-
-	}
-
-	virtual void visit( InitExpr *  ) override final {
-
-	}
-
-	virtual void visit( DeletedExpr * ) override final {
-
-	}
-
-	virtual void visit( DefaultArgExpr * ) override final {
-
-	}
-
-	virtual void visit( GenericExpr * ) override final {
-
+	virtual void visit( TypeExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::TypeExpr(
+				old->location,
+				GET_ACCEPT_1(type, Type)
+			)
+		);
+	}
+
+	virtual void visit( AsmExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::AsmExpr(
+				old->location,
+				GET_ACCEPT_1(inout, Expr),
+				GET_ACCEPT_1(constraint, Expr),
+				GET_ACCEPT_1(operand, Expr)
+			)
+		);
+	}
+
+	virtual void visit( ImplicitCopyCtorExpr * old ) override final {
+		auto rslt = new ast::ImplicitCopyCtorExpr(
+			old->location,
+			GET_ACCEPT_1(callExpr, ApplicationExpr)
+		);
+
+		rslt->tempDecls = GET_ACCEPT_V(tempDecls, ObjectDecl);
+		rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
+		rslt->dtors = GET_ACCEPT_V(dtors, Expr);
+
+		this->node = visitBaseExpr( old, rslt );
+	}
+
+	virtual void visit( ConstructorExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::ConstructorExpr(
+				old->location,
+				GET_ACCEPT_1(callExpr, Expr)
+			)
+		);
+	}
+
+	virtual void visit( CompoundLiteralExpr * old ) override final {
+		this->node = visitBaseExpr_SkipResultType( old,
+			new ast::CompoundLiteralExpr(
+				old->location,
+				GET_ACCEPT_1(result, Type),
+				GET_ACCEPT_1(initializer, Init)
+			)
+		);
+	}
+
+	virtual void visit( RangeExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::RangeExpr(
+				old->location,
+				GET_ACCEPT_1(low, Expr),
+				GET_ACCEPT_1(high, Expr)
+			)
+		);
+	}
+
+	virtual void visit( UntypedTupleExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::UntypedTupleExpr(
+				old->location,
+				GET_ACCEPT_V(exprs, Expr)
+			)
+		);
+	}
+
+	virtual void visit( TupleExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::TupleExpr(
+				old->location,
+				GET_ACCEPT_V(exprs, Expr)
+			)
+		);
+	}
+
+	virtual void visit( TupleIndexExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::TupleIndexExpr(
+				old->location,
+				GET_ACCEPT_1(tuple, Expr),
+				old->index
+			)
+		);
+	}
+
+	virtual void visit( TupleAssignExpr * old ) override final {
+		this->node = visitBaseExpr_SkipResultType( old,
+			new ast::TupleAssignExpr(
+				old->location,
+				GET_ACCEPT_1(result, Type),
+				GET_ACCEPT_1(stmtExpr, StmtExpr)
+			)
+		);
+	}
+
+	virtual void visit( StmtExpr * old ) override final {
+		auto rslt = new ast::StmtExpr(
+			old->location,
+			GET_ACCEPT_1(statements, CompoundStmt)
+		);
+		rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
+		rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
+
+		this->node = visitBaseExpr_SkipResultType( old, rslt );
+	}
+
+	virtual void visit( UniqueExpr * old ) override final {
+		auto rslt = new ast::UniqueExpr(
+			old->location,
+			GET_ACCEPT_1(expr, Expr)
+		);
+		rslt->object = GET_ACCEPT_1(object, ObjectDecl);
+		rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
+
+		this->node = visitBaseExpr( old, rslt );
+	}
+
+	virtual void visit( UntypedInitExpr * old ) override final {
+		std::vector<ast::InitAlternative> initAlts;
+		for (auto ia : old->initAlts) {
+			initAlts.push_back(ast::InitAlternative(
+				getAccept1< ast::Type, Type * >( ia.type ),
+				getAccept1< ast::Designation, Designation * >( ia.designation )
+			));
+		}
+		this->node = visitBaseExpr( old,
+			new ast::UntypedInitExpr(
+				old->location,
+				GET_ACCEPT_1(expr, Expr),
+				std::move(initAlts)
+			)
+		);
+	}
+
+	virtual void visit( InitExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::InitExpr(
+				old->location,
+				GET_ACCEPT_1(expr, Expr),
+				GET_ACCEPT_1(designation, Designation)
+			)
+		);
+	}
+
+	virtual void visit( DeletedExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::DeletedExpr(
+				old->location,
+				GET_ACCEPT_1(expr, Expr),
+				inCache(old->deleteStmt) ?
+					this->node :
+					GET_ACCEPT_1(deleteStmt, Node)
+			)
+		);
+	}
+
+	virtual void visit( DefaultArgExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::DefaultArgExpr(
+				old->location,
+				GET_ACCEPT_1(expr, Expr)
+			)
+		);
+	}
+
+	virtual void visit( GenericExpr * old ) override final {
+		std::vector<ast::GenericExpr::Association> associations;
+		for (auto association : old->associations) {
+			associations.push_back(ast::GenericExpr::Association(
+				getAccept1< ast::Type, Type * >( association.type ),
+				getAccept1< ast::Expr, Expression * >( association.expr )
+			));
+		}
+		this->node = visitBaseExpr( old,
+			new ast::GenericExpr(
+				old->location,
+				GET_ACCEPT_1(control, Expr),
+				std::move(associations)
+			)
+		);
 	}
 
@@ -2262,31 +2642,52 @@
 	}
 
-	virtual void visit( Designation * ) override final {
-
-	}
-
-	virtual void visit( SingleInit * ) override final {
-
-	}
-
-	virtual void visit( ListInit * ) override final {
-
-	}
-
-	virtual void visit( ConstructorInit * ) override final {
-
+	virtual void visit( Designation * old ) override final {
+		this->node = new ast::Designation(
+			old->location,
+			GET_ACCEPT_V(designators, Expr)
+		);
+	}
+
+	virtual void visit( SingleInit * old ) override final {
+		this->node = new ast::SingleInit(
+			old->location,
+			GET_ACCEPT_1(value, Expr),
+			(old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
+		);
+	}
+
+	virtual void visit( ListInit * old ) override final {
+		this->node = new ast::ListInit(
+			old->location,
+			GET_ACCEPT_V(initializers, Init),
+			GET_ACCEPT_V(designations, Designation),
+			(old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
+		);
+	}
+
+	virtual void visit( ConstructorInit * old ) override final {
+		this->node = new ast::ConstructorInit(
+			old->location,
+			GET_ACCEPT_1(ctor, Stmt),
+			GET_ACCEPT_1(dtor, Stmt),
+			GET_ACCEPT_1(init, Init)
+		);
 	}
 
 	virtual void visit( Constant * ) override final {
-
-	}
-
-	virtual void visit( Attribute * ) override final {
-
+		// Handled in visit( ConstantEpxr * ).
+		// In the new tree, Constant fields are inlined into containing ConstantExpression.
+		assert( 0 );
+	}
+
+	virtual void visit( Attribute * old ) override final {
+		this->node = new ast::Attribute(
+			old->name,
+			GET_ACCEPT_V( parameters, Expr )
+		);
 	}
 
 	virtual void visit( AttrExpr * ) override final {
-
-		assert( 0 );
+		assertf( false, "AttrExpr deprecated in new AST." );
 	}
 };
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/AST/Expr.cpp	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -335,4 +335,10 @@
 }
 
+TupleAssignExpr::TupleAssignExpr( 
+	const CodeLocation & loc, const Type * result, const StmtExpr * s )
+: Expr( loc, result ), stmtExpr() {
+	stmtExpr = s;
+}
+
 // --- StmtExpr
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/AST/Expr.hpp	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -30,4 +30,6 @@
 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
+class ConverterOldToNew;
+
 namespace ast {
 
@@ -528,5 +530,5 @@
 	std::vector<ptr<ObjectDecl>> tempDecls;
 	std::vector<ptr<ObjectDecl>> returnDecls;
-	std::vector<ptr<ObjectDecl>> dtors;
+	std::vector<ptr<Expr>> dtors;
 
 	ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
@@ -635,6 +637,11 @@
 
 	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
+
+	friend class ::ConverterOldToNew;
+
 private:
 	TupleAssignExpr * clone() const override { return new TupleAssignExpr{ *this }; }
+    TupleAssignExpr( const CodeLocation & loc, const Type * result, const StmtExpr * s );
+
 	MUTATE_FRIEND
 };
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/AST/Stmt.hpp	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -96,4 +96,5 @@
 };
 
+/// Assembly statement `asm ... ( "..." : ... )`
 class AsmStmt final : public Stmt {
 public:
@@ -118,4 +119,5 @@
 };
 
+/// C-preprocessor directive `#...`
 class DirectiveStmt final : public Stmt {
 public:
@@ -132,4 +134,5 @@
 };
 
+/// If conditional statement `if (...) ... else ...`
 class IfStmt final : public Stmt {
 public:
@@ -151,4 +154,5 @@
 };
 
+/// Switch or choose conditional statement `switch (...) { ... }`
 class SwitchStmt final : public Stmt {
 public:
@@ -166,4 +170,5 @@
 };
 
+/// Case label `case ...:` `default:`
 class CaseStmt final : public Stmt {
 public:
@@ -183,4 +188,5 @@
 };
 
+/// While loop `while (...) ...` `do ... while (...);
 class WhileStmt final : public Stmt {
 public:
@@ -201,4 +207,5 @@
 };
 
+/// For loop `for (... ; ... ; ...) ...`
 class ForStmt final : public Stmt {
 public:
@@ -219,4 +226,5 @@
 };
 
+/// Branch control flow statement `goto ...` `break` `continue` `fallthru`
 class BranchStmt final : public Stmt {
 public:
@@ -246,4 +254,5 @@
 };
 
+/// Return statement `return ...`
 class ReturnStmt final : public Stmt {
 public:
@@ -259,4 +268,5 @@
 };
 
+/// Throw statement `throw ...`
 class ThrowStmt final : public Stmt {
 public:
@@ -277,4 +287,5 @@
 };
 
+/// Try statement `try { ... } ...`
 class TryStmt final : public Stmt {
 public:
@@ -294,4 +305,5 @@
 };
 
+/// Catch clause of try statement
 class CatchStmt final : public Stmt {
 public:
@@ -313,4 +325,5 @@
 };
 
+/// Finally clause of try statement
 class FinallyStmt final : public Stmt {
 public:
@@ -327,4 +340,5 @@
 };
 
+/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
 class WaitForStmt final : public Stmt {
 public:
@@ -364,4 +378,5 @@
 };
 
+/// With statement `with (...) ...`
 class WithStmt final : public Stmt {
 public:
@@ -379,4 +394,5 @@
 };
 
+/// Any declaration in a (compound) statement.
 class DeclStmt final : public Stmt {
 public:
@@ -392,4 +408,5 @@
 };
 
+/// Represents an implicit application of a constructor or destructor.
 class ImplicitCtorDtorStmt final : public Stmt {
 public:
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/SynTree/Expression.h	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -741,4 +741,8 @@
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+
+	friend class ConverterNewToOld;
+  private:
+    TupleAssignExpr( StmtExpr * stmts );
 };
 
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision e9b444897a7f44c690ecbcd5c3178b3cfd90c195)
+++ src/SynTree/TupleExpr.cc	(revision f4c2f1a02753f281c59f650f4c89475f36279b0c)
@@ -105,4 +105,10 @@
 }
 
+TupleAssignExpr::TupleAssignExpr( 
+	StmtExpr * s )
+: Expression(), stmtExpr(s) {
+}
+
+
 TupleAssignExpr::~TupleAssignExpr() {
 	delete stmtExpr;
