Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 68c9165ba8977f22fd2ed8d7175c671e03359a1a)
+++ src/AST/Convert.cpp	(revision 20a5977853b171b0b954c0b3e9fc8c385f94e3cf)
@@ -700,58 +700,24 @@
 	}
 
-	bool isIntlikeConstantType(const ast::Type *t) {
-		if ( const ast::BasicType * basicType = dynamic_cast< const ast::BasicType * >( t ) ) {
-			if ( basicType->isInteger() ) {
-				return true;
-			}
-		} else if ( dynamic_cast< const ast::OneType * >( t ) ) {
-			return true;
-		} else if ( dynamic_cast< const ast::ZeroType * >( t ) ) {
-			return true;
-		} else if ( dynamic_cast< const ast::PointerType * >( t ) ) {
-			// null pointer constants, with zero int-values
-			return true;
-		}
-		return false;
-	}
-
-	bool isFloatlikeConstantType(const ast::Type *t) {
-		if ( const ast::BasicType * bty = dynamic_cast< const ast::BasicType * >( t ) ) {
-			if ( ! bty->isInteger() ) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	bool isStringlikeConstantType(const ast::Type *t) {
-		if ( const ast::ArrayType * aty = dynamic_cast< const ast::ArrayType * >( t ) ) {
-			if ( const ast::BasicType * bty = aty->base.as<ast::BasicType>() ) {
-			   if ( bty->kind == ast::BasicType::Kind::Char ) {
-				   return true;
-			   }
-			}
-		}
-		return false;
-	}
-
 	const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
 		ConstantExpr *rslt = nullptr;
-		if (isIntlikeConstantType(node->result)) {
-			rslt = new ConstantExpr(Constant(
-				get<Type>().accept1(node->result),
+		switch ( node->kind ) {
+		case ast::ConstantExpr::Integer:
+			rslt = new ConstantExpr{Constant{
+				get<Type>().accept1( node->result ),
 				node->rep,
 				(unsigned long long) node->intValue()
-			));
-		} else if (isFloatlikeConstantType(node->result)) {
-			rslt = new ConstantExpr(Constant(
+			}};
+			break;
+		case ast::ConstantExpr::FloatingPoint:
+			rslt = new ConstantExpr{Constant{
 				get<Type>().accept1(node->result),
 				node->rep,
 				(double) node->floatValue()
-			));
-		} else if (isStringlikeConstantType(node->result)) {
-			rslt = new ConstantExpr(Constant::from_string(
-				node->rep
-			));
+			}};
+			break;
+		case ast::ConstantExpr::String:
+			rslt = new ConstantExpr{Constant::from_string( node->rep )};
+			break;
 		}
 		assert(rslt);
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 68c9165ba8977f22fd2ed8d7175c671e03359a1a)
+++ src/AST/Expr.cpp	(revision 20a5977853b171b0b954c0b3e9fc8c385f94e3cf)
@@ -241,5 +241,6 @@
 			FixedLen, DynamicDim },
 		std::string{"\""} + s + "\"",
-		(unsigned long long)0 };
+		(unsigned long long)0,
+		ConstantExpr::String };
 }
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 68c9165ba8977f22fd2ed8d7175c671e03359a1a)
+++ src/AST/Expr.hpp	(revision 20a5977853b171b0b954c0b3e9fc8c385f94e3cf)
@@ -337,10 +337,12 @@
 public:
 	std::string rep;
+	enum Kind { Integer, FloatingPoint, String } kind;
 
 	ConstantExpr(
-		const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v )
-	: Expr( loc, ty ), val( v ), rep( r ) {}
+		const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v,
+		Kind k = Integer )
+	: Expr( loc, ty ), val( v ), rep( r ), kind( k ) {}
 	ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
-	: Expr( loc, ty ), val( v ), rep( r ) {}
+	: Expr( loc, ty ), val( v ), rep( r ), kind( FloatingPoint ) {}
 
 	/// Gets the value of this constant as an integer
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 68c9165ba8977f22fd2ed8d7175c671e03359a1a)
+++ src/AST/Print.cpp	(revision 20a5977853b171b0b954c0b3e9fc8c385f94e3cf)
@@ -59,4 +59,23 @@
 	}
 
+	/// call if mandatory field is missing
+	void undefined() {
+		os << "UNDEFINED";
+	}
+
+	/// call for fields that should be mandatory
+	void safe_print( const ast::Node * n ) {
+		if ( n ) n->accept( *this );
+		else undefined();
+	}
+
+	/// call to print short form. Incorporates features of safe_print()
+	void short_print( const ast::Node * n ) {
+		if ( ! n ) { undefined(); return; }
+		bool old_short = short_mode; short_mode = true;
+		n->accept( *this );
+		short_mode = old_short;
+	}
+
 
 	static const char* Names[];
@@ -99,4 +118,27 @@
 	}
 
+	void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
+		switch ( inferred.mode ) {
+		case ast::Expr::InferUnion::Empty: return;
+		case ast::Expr::InferUnion::Slots: {
+			os << indent << "with " << inferred.data.resnSlots.size() << " pending inference slots" 
+			   << std::endl;
+			return;
+		}
+		case ast::Expr::InferUnion::Params: {
+			os << indent << "with inferred parameters " << level << ":" << std::endl;
+			++indent;
+			for ( const auto & i : inferred.data.inferParams ) {
+				os << indent;
+				short_print( Decl::fromId( i.second.decl ) );
+				os << std::endl;
+				print( i.second.expr->inferred, level+1 );
+			}
+			--indent;
+			return;
+		}
+		}
+	}
+
 	void print( const ast::ParameterizedType::ForallList & forall ) {
 		if ( forall.empty() ) return;	
@@ -122,4 +164,75 @@
 		printAll( params );
 		--indent;
+	}
+
+	void print( const ast::AggregateDecl * node ) {
+		os << node->typeString() << " " << node->name << ":";
+		if ( node->linkage != Linkage::Cforall ) {
+			os << " " << Linkage::name( node->linkage );
+		} // if
+		os << " with body : " << (node->body ? "yes " : "no ");
+
+		if ( ! node->params.empty() ) {
+			os << endl << indent << "... with parameters" << endl;
+			++indent;
+			printAll( node->params );
+			--indent;
+		} // if
+		if ( ! node->members.empty() ) {
+			os << endl << indent << "... with members" << endl;
+			++indent;
+			printAll( node->members );
+			--indent;
+		} // if
+		if ( ! node->attributes.empty() ) {
+			os << endl << indent << "... with attributes" << endl;
+			++indent;
+			printAll( node->attributes );
+			--indent;
+		} // if
+		os << endl;
+	}
+
+	void print( const ast::NamedTypeDecl * node ) {
+		if ( !node->name.empty() ) os << node->name << ": ";
+
+		if ( node->linkage != Linkage::Cforall ) {
+			os << Linkage::name( node->linkage ) << " ";
+		} // if
+		print( node->storage );
+		os << node->typeString();
+		if ( node->base ) {
+			os << " for ";
+			++indent;
+			node->base->accept( *this );
+			--indent;
+		} // if
+		if ( ! node->params.empty() ) {
+			os << endl << indent << "... with parameters" << endl;
+			++indent;
+			printAll( node->params );
+			--indent;
+		} // if
+		if ( ! node->assertions.empty() ) {
+			os << endl << indent << "... with assertions" << endl;
+			++indent;
+			printAll( node->assertions );
+			--indent;
+		} // if
+	}
+
+	void postprint( const ast::Expr * node ) {
+		print( node->inferred );
+
+		if ( node->env ) {
+			os << std::endl << indent << "... with environment:" << std::endl;
+			++indent;
+			node->env->accept( *this );
+			--indent;
+		}
+		
+		if ( node->extension ) {
+			os << std::endl << indent << "... with extension";
+		}
 	}
 
@@ -138,60 +251,4 @@
 		print( node->qualifiers );
 	}
-	
-	void print( const ast::AggregateDecl * node ) {
-		os << node->typeString() << " " << node->name << ":";
-		if ( node->linkage != Linkage::Cforall ) {
-			os << " " << Linkage::name( node->linkage );
-		} // if
-		os << " with body : " << (node->body ? "yes " : "no ");
-
-		if ( ! node->params.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			++indent;
-			printAll( node->params );
-			--indent;
-		} // if
-		if ( ! node->members.empty() ) {
-			os << endl << indent << "... with members" << endl;
-			++indent;
-			printAll( node->members );
-			--indent;
-		} // if
-		if ( ! node->attributes.empty() ) {
-			os << endl << indent << "... with attributes" << endl;
-			++indent;
-			printAll( node->attributes );
-			--indent;
-		} // if
-		os << endl;
-	}
-
-	void print( const ast::NamedTypeDecl * node ) {
-		if ( !node->name.empty() ) os << node->name << ": ";
-
-		if ( node->linkage != Linkage::Cforall ) {
-			os << Linkage::name( node->linkage ) << " ";
-		} // if
-		print( node->storage );
-		os << node->typeString();
-		if ( node->base ) {
-			os << " for ";
-			++indent;
-			node->base->accept( *this );
-			--indent;
-		} // if
-		if ( ! node->params.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			++indent;
-			printAll( node->params );
-			--indent;
-		} // if
-		if ( ! node->assertions.empty() ) {
-			os << endl << indent << "... with assertions" << endl;
-			++indent;
-			printAll( node->assertions );
-			--indent;
-		} // if
-	}
 
 public:
@@ -208,5 +265,5 @@
 			node->type->accept( *this );
 		} else {
-			os << " untyped entity ";
+			os << "untyped entity";
 		} // if
 
@@ -254,5 +311,5 @@
 			node->type->accept( *this );
 		} else {
-			os << "untyped entity ";
+			os << "untyped entity";
 		} // if
 
@@ -331,5 +388,5 @@
 		++indent;
 		os << "Expression Statement:" << endl << indent;
-		node->expr->accept( *this );
+		safe_print( node->expr );
 		--indent;
 		return node;
@@ -366,5 +423,5 @@
 		os << indent+1;
 		++indent;
-		node->cond->accept( *this );
+		safe_print( node->cond );
 		--indent;
 
@@ -384,5 +441,5 @@
 		++indent;
 		os << indent;
-		node->thenPart->accept( *this );
+		safe_print( node->thenPart );
 		--indent;
 
@@ -458,48 +515,144 @@
 
 	virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
+		++indent;
+		os << "Application of" << std::endl << indent;
+		safe_print( node->func );
+		os << std::endl;
+		if ( ! node->args.empty() ) {
+			os << indent << "... to arguments" << std::endl;
+			printAll( node->args );
+		}
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
+		++indent;
+		os << "Applying untyped:" << std::endl;
+		os << indent;
+		safe_print( node->func );
+		os << std::endl << indent-1 << "...to:" << std::endl;
+		printAll( node->args );
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::NameExpr * node ) {
+		os << "Name: " << node->name;
+		postprint( node );
+		
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
+		os << "Address of:" << std::endl;
+		++indent;
+		os << indent;
+		safe_print( node->arg );
+
+		--indent;
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
+		os << "Address of label:" << node->arg;
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::CastExpr * node ) {
+		++indent;
+		os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << std::endl << indent;
+		safe_print( node->arg );
+		os << std::endl << indent-1 << "... to:";
+		if ( ! node->result ) {
+			os << " ";
+			undefined();
+		} else if ( node->result->isVoid() ) {
+			os << " nothing";
+		} else {
+			os << std::endl << indent;
+			node->result->accept( *this );
+		} // if
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
+		++indent;
+		os << "Keyword Cast of:" << std::endl << indent;
+		safe_print( node->arg );
+		--indent;
+		os << std::endl << indent << "... to: " << node->targetString();
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
+		++indent;
+		os << "Virtual Cast of:" << std::endl << indent;
+		safe_print( node->arg );
+		os << std::endl << indent-1 << "... to:";
+		if ( ! node->result ) {
+			os << " unknown";
+		} else {
+			os << std::endl << indent;
+			node->result->accept( *this );
+		}
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
+		++indent;
+		os << "Untyped Member Expression, with field: " << std::endl << indent;
+		safe_print( node->member );
+		os << indent-1 << "... from aggregate:" << std::endl << indent;
+		safe_print( node->aggregate );
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
+		++indent;
+		os << "Member Expression, with field:" << std::endl << indent;
+		safe_print( node->member );
+		os << std::endl << indent-1 << "... from aggregate:" << std::endl << indent;
+		safe_print( node->aggregate );
+		--indent;
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
+		os << "Variable Expression: ";
+		short_print( node->var );
+		postprint( node );
+
 		return node;
 	}
 
 	virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
+		os << "Constant Expression (" << node->rep;
+		if ( node->result ) {
+			os << ": ";
+			node->result->accept( *this );
+		}
+		os << ")";
+		postprint( node );
+
 		return node;
 	}
@@ -635,10 +788,6 @@
 			}
 		}
-
-		if ( node->base ) {
-			node->base->accept( *this );
-		} else {
-			os << "UNDEFINED";
-		}
+		safe_print( node->base );
+
 		return node;
 	}
@@ -658,9 +807,5 @@
 		}
 
-		if ( node->base ) {
-			node->base->accept( *this );
-		} else {
-			os << "UNDEFINED";
-		}
+		safe_print( node->base );
 
 		if ( node->dimension ) {
@@ -674,11 +819,6 @@
 	virtual const ast::Type * visit( const ast::ReferenceType * node ) {
 		preprint( node );
-
 		os << "reference to ";
-		if ( node->base ) {
-			node->base->accept( *this );
-		} else {
-			os << "UNDEFINED";
-		}
+		safe_print( node->base );
 
 		return node;
@@ -687,10 +827,9 @@
 	virtual const ast::Type * visit( const ast::QualifiedType * node ) {
 		preprint( node );
-
 		++indent;
 		os << "Qualified Type:" << std::endl << indent;
-		node->parent->accept( *this );
+		safe_print( node->parent );
 		os << std::endl << indent;
-		node->child->accept( *this );
+		safe_print( node->child );
 		os << std::endl;
 		--indent;
@@ -701,5 +840,5 @@
 	virtual const ast::Type * visit( const ast::FunctionType * node ) {
 		preprint( node );
-
+		
 		os << "function" << std::endl;
 		if ( ! node->params.empty() ) {
@@ -730,5 +869,4 @@
 	virtual const ast::Type * visit( const ast::StructInstType * node ) {
 		preprint( node );
-
 		os << "instance of struct " << node->name;
 		if ( node->base ) {
@@ -742,5 +880,4 @@
 	virtual const ast::Type * visit( const ast::UnionInstType * node ) {
 		preprint( node );
-
 		os << "instance of union " << node->name;
 		if ( node->base ) {
@@ -754,5 +891,4 @@
 	virtual const ast::Type * visit( const ast::EnumInstType * node ) {
 		preprint( node );
-
 		os << "instance of enum " << node->name;
 		if ( node->base ) {
@@ -766,5 +902,4 @@
 	virtual const ast::Type * visit( const ast::TraitInstType * node ) {
 		preprint( node );
-
 		os << "instance of trait " << node->name;
 		print( node->params );
@@ -775,5 +910,4 @@
 	virtual const ast::Type * visit( const ast::TypeInstType * node ) {
 		preprint( node );
-
 		os << "instance of type " << node->name 
 		   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
@@ -785,5 +919,4 @@
 	virtual const ast::Type * visit( const ast::TupleType * node ) {
 		preprint( node );
-
 		os << "tuple of types" << std::endl;
 		++indent;
@@ -796,12 +929,7 @@
 	virtual const ast::Type * visit( const ast::TypeofType * node ) {
 		preprint( node );
-
 		if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
 		os << "type-of expression ";
-		if ( node->expr ) {
-			node->expr->accept( *this );
-		} else {
-			os << "UNDEFINED";
-		}
+		safe_print( node->expr );
 
 		return node;
@@ -847,5 +975,5 @@
 	virtual const ast::Init * visit( const ast::SingleInit * node ) {
 		os << "Simple Initializer: ";
-		node->value->accept( *this );
+		safe_print( node->value );
 		return node;
 	}
@@ -910,5 +1038,5 @@
 			os << indent+1 << i.first << " -> ";
 			indent += 2;
-			i.second->accept( *this );
+			safe_print( i.second );
 			indent -= 2;
 			os << std::endl;
@@ -918,5 +1046,5 @@
 			os << indent+1 << i->first << " -> ";
 			indent += 2;
-			i->second->accept( *this );
+			safe_print( i->second );
 			indent -= 2;
 			os << std::endl;
