Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/AST/Convert.cpp	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -734,15 +734,6 @@
 	const ast::Expr * visit( const ast::VariableExpr * node ) override final {
 		auto expr = new VariableExpr();
+		expr->var = get<DeclarationWithType>().accept1(node->var);
 		visitBaseExpr( node, expr );
-		expr->var = get<DeclarationWithType>().accept1(node->var);
-		Type * type = expr->var->get_type()->clone();
-		if(FunctionType * ft = dynamic_cast<FunctionType*>(type)) {
-			if(node->result.as<ast::PointerType>()) {
-				type = new PointerType({}, ft);
-			}
-		}
-
-		type->set_lvalue( true );
-		expr->result = type ;
 		this->node = expr;
 		return nullptr;
@@ -750,29 +741,18 @@
 
 	const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
-		ConstantExpr *rslt = nullptr;
-		switch ( node->kind ) {
-		case ast::ConstantExpr::Integer:
-			rslt = new ConstantExpr{Constant{
-				get<Type>().accept1( node->result ),
-				node->rep,
-				(unsigned long long) node->intValue()
-			}};
-			break;
-		case ast::ConstantExpr::FloatingPoint:
-			rslt = new ConstantExpr{Constant{
-				get<Type>().accept1(node->result),
-				node->rep,
-				(double) node->floatValue()
-			}};
-			break;
-		case ast::ConstantExpr::String:
-			rslt = new ConstantExpr{Constant{
-				get<Type>().accept1( node->result ),
-				node->rep,
-				(long long unsigned int)0
-			}};
-			break;
-		}
-		assert(rslt);
+		// Old world:   two types: rslt->constant.type, rslt->result
+		// New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
+		//              preserving underlyer because the correct type for string literals is complicated to construct,
+	    //              and distinguishing a string from other literals using the type is hard to do accurately
+		// Both worlds: the outer, expression-level type can change during resolution
+		//              for a string, that's char[k] before-resolve and char * after
+		// Old world:   the inner Constant type stays what it was built with
+		//              for a string, that's char[k] always
+		// Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
+        //              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
+		ConstantExpr *rslt = new ConstantExpr(Constant(
+			get<Type>().accept1(node->underlyer),
+			node->rep,
+			node->ival));
 		auto expr = visitBaseExpr( node, rslt );
 		this->node = expr;
@@ -2153,88 +2133,18 @@
 		);
 
-		visitBaseExpr_SkipResultType( old,
-			expr
-		);
-
 		expr->var = GET_ACCEPT_1(var, DeclWithType);
-		expr->result = expr->var->get_type();
-		if(const ast::FunctionType * ft = expr->result.as<ast::FunctionType>()) {
-			if(dynamic_cast<PointerType *>(old->result)) {
-				expr->result = new ast::PointerType(ft);
-			}
-		}
-		add_qualifiers( expr->result, ast::CV::Lvalue );
-		this->node = expr;
-	}
-
-	bool isIntlikeConstantType(const Type *t) {
-		if ( const BasicType * basicType = dynamic_cast< const BasicType * >( t ) ) {
-			if ( basicType->isInteger() ) {
-				return true;
-			}
-		} else if ( dynamic_cast< const OneType * >( t ) ) {
-			return true;
-		} else if ( dynamic_cast< const ZeroType * >( t ) ) {
-			return true;
-		} else if ( dynamic_cast< const PointerType * >( t ) ) {
-			// null pointer constants, with zero int-values
-			return true;
-		}
-		return false;
-	}
-
-	int isFloatlikeConstantType(const Type *t) {
-		if ( const BasicType * bty = dynamic_cast< const BasicType * >( t ) ) {
-			if ( ! bty->isInteger() ) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	int isStringlikeConstantType(const Type *t) {
-		const Type *referentType = nullptr;
-		if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) {
-			referentType = aty->base;
-		} else if ( const PointerType * pty = dynamic_cast< const PointerType * >( t ) ) {
-			referentType = pty->base;
-		}
-		if (referentType) {
-			if ( const BasicType * bty = dynamic_cast< const BasicType * >( referentType ) ) {
-			   if ( bty->kind == BasicType::Kind::Char ) {
-				   return true;
-			   }
-			}
-		}
-		return false;
+		visitBaseExpr( old, expr );
+
+		this->node = expr;
 	}
 
 	virtual void visit( ConstantExpr * old ) override final {
-		ast::ConstantExpr *rslt = nullptr;
-		if (isStringlikeConstantType(old->result)) {
-			rslt = new ast::ConstantExpr(
-				old->location,
-				GET_ACCEPT_1(result, Type),
-				old->constant.get_value(),
-				0,
-				ast::ConstantExpr::Kind::String
-			);
-		} else if (isIntlikeConstantType(old->result)) {
-			rslt = new ast::ConstantExpr(
-				old->location,
-				GET_ACCEPT_1(result, Type),
-				old->constant.get_value(),
-				(unsigned long long) old->intValue(),
-				ast::ConstantExpr::Kind::Integer
-			);
-		} else if (isFloatlikeConstantType(old->result)) {
-			rslt = new ast::ConstantExpr(
-				old->location,
-				GET_ACCEPT_1(result, Type),
-				old->constant.get_value(),
-				(double) old->constant.get_dval()
-			);
-		}
-		assert(rslt);
+		ast::ConstantExpr *rslt = new ast::ConstantExpr(
+			old->location,
+			GET_ACCEPT_1(result, Type),
+			old->constant.get_value(),
+			old->constant.ival
+		);
+		rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.get_type() );
 		this->node = visitBaseExpr( old, rslt );
 	}
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/AST/Expr.cpp	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May 15 17:00:00 2019
-// Last Modified By : Aaron B. Moss
-// Created On       : Wed May 15 17:00:00 2019
-// Update Count     : 1
+// Last Modified By : Andrew Beach
+// Created On       : Thr Jun 13 13:38:00 2019
+// Update Count     : 2
 //
 
@@ -194,5 +194,6 @@
 	if ( const BasicType * bty = result.as< BasicType >() ) {
 		if ( bty->isInteger() ) {
-			return val.ival;
+			assert(ival);
+			return ival.value();
 		}
 	} else if ( result.as< ZeroType >() ) {
@@ -204,21 +205,7 @@
 }
 
-double ConstantExpr::floatValue() const {
-	if ( const BasicType * bty = result.as< BasicType >() ) {
-		if ( ! bty->isInteger() ) {
-			return val.dval;
-		}
-	}
-	SemanticError( this, "Constant expression of non-floating-point type " );
-}
-
 ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
 	return new ConstantExpr{
 		loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
-}
-
-ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {
-	return new ConstantExpr{
-		loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };
 }
 
@@ -232,20 +219,4 @@
 		loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
 		(unsigned long long)i };
-}
-
-ConstantExpr * ConstantExpr::from_double( const CodeLocation & loc, double d ) {
-	return new ConstantExpr{ loc, new BasicType{ BasicType::Double }, std::to_string( d ), d };
-}
-
-ConstantExpr * ConstantExpr::from_string( const CodeLocation & loc, const std::string & s ) {
-	return new ConstantExpr{
-		loc,
-		new ArrayType{
-			new BasicType{ BasicType::Char, CV::Const },
-			ConstantExpr::from_int( loc, s.size() + 1 /* null terminator */ ),
-			FixedLen, DynamicDim },
-		std::string{"\""} + s + "\"",
-		(unsigned long long)0,
-		ConstantExpr::String };
 }
 
@@ -382,5 +353,5 @@
 
 UniqueExpr::UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i )
-: Expr( loc, e->result ), id( i ) {
+: Expr( loc, e->result ), expr( e ), id( i ) {
 	assert( expr );
 	if ( id == -1ull ) {
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/AST/Expr.hpp	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -22,4 +22,5 @@
 #include <utility>        // for move
 #include <vector>
+#include <optional>
 
 #include "Fwd.hpp"        // for UniqueId
@@ -32,4 +33,5 @@
 
 class ConverterOldToNew;
+class ConverterNewToOld;
 
 namespace ast {
@@ -346,41 +348,28 @@
 };
 
-/// A compile-time constant
+/// A compile-time constant.
+/// Mostly carries C-source text from parse to code-gen, without interpretation.  E.g. strings keep their outer quotes and never have backslashes interpreted.
+/// Integer constants get special treatment, e.g. for verifying array operations, when an integer constant occurs as the length of an array.
 class ConstantExpr final : public Expr {
-	union Val {
-		unsigned long long ival;
-		double dval;
-
-		Val( unsigned long long i ) : ival( i ) {}
-		Val( double d ) : dval( d ) {}
-	} val;
-public:
+public:
+	// Representation of this constant, as it occurs in .cfa source and .cfa.cc result.
 	std::string rep;
-	enum Kind { Integer, FloatingPoint, String } kind;
 
 	ConstantExpr(
-		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 ), kind( FloatingPoint ) {}
-
-	/// Gets the value of this constant as an integer
+		const CodeLocation & loc, const Type * ty, const std::string & r, 
+			std::optional<unsigned long long> i )
+	: Expr( loc, ty ), rep( r ), ival( i ) {}
+
+	/// Gets the integer value of this constant, if one is appropriate to its type.
+	/// Throws a SemanticError if the type is not appropriate for value-as-integer.
+	/// Suffers an assertion failure the type is appropriate but no integer value was supplied to the constructor.
 	long long int intValue() const;
-	/// Gets the value of this constant as floating point
-	double floatValue() const;
 
 	/// generates a boolean constant of the given bool
 	static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
-	/// generates a char constant of the given char
-	static ConstantExpr * from_char( const CodeLocation & loc, char c );
 	/// generates an integer constant of the given int
 	static ConstantExpr * from_int( const CodeLocation & loc, int i );
 	/// generates an integer constant of the given unsigned long int
 	static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
-	/// generates a floating point constant of the given double
-	static ConstantExpr * from_double( const CodeLocation & loc, double d );
-	/// generates an array of chars constant of the given string
-	static ConstantExpr * from_string( const CodeLocation & loc, const std::string & s );
 	/// generates a null pointer value for the given type. void * if omitted.
 	static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
@@ -390,4 +379,13 @@
 	ConstantExpr * clone() const override { return new ConstantExpr{ *this }; }
 	MUTATE_FRIEND
+
+	std::optional<unsigned long long> ival;
+
+	// Intended only for legacy support of roundtripping the old AST.
+	// Captures the very-locally inferred type, before the resolver modifies the type of this ConstantExpression.
+	// In the old AST it's constExpr->constant.type
+	ptr<Type> underlyer;
+	friend class ::ConverterOldToNew;
+	friend class ::ConverterNewToOld;
 };
 
@@ -693,5 +691,5 @@
 	unsigned long long id;
 
-	UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i = -1 );
+	UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i = -1ull );
 
 	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
