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 ); }
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/Parser/ExpressionNode.cc	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -357,5 +357,5 @@
 									new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
 									false, false );
-	Expression * ret = new ConstantExpr( Constant( at, str, (unsigned long long int)0 ) ); // constant 0 is ignored for pure string value
+	Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
 	if ( units.length() != 0 ) {
 		ret = new UntypedExpr( new NameExpr( units ), { ret } );
Index: src/ResolvExpr/Candidate.hpp
===================================================================
--- src/ResolvExpr/Candidate.hpp	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/ResolvExpr/Candidate.hpp	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed Jun 5 14:30:00 2019
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed Jun 5 14:30:00 2019
-// Update Count     : 1
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Jun 12 14:15:00 2019
+// Update Count     : 2
 //
 
@@ -49,16 +49,16 @@
 
 	Candidate() : expr(), cost( Cost::zero ), cvtCost( Cost::zero ), env(), open(), need() {}
-	
+
 	Candidate( const ast::Expr * x, const ast::TypeEnvironment & e )
 	: expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {}
 
 	Candidate( const Candidate & o, const ast::Expr * x )
-	: expr( x ), cost( o.cost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ), 
+	: expr( x ), cost( o.cost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ),
 	  need( o.need ) {}
-	
-	Candidate( 
-		const ast::Expr * x, ast::TypeEnvironment && e, ast::OpenVarSet && o, 
-		ast::AssertionSet && n, const Cost & c )
-	: expr( x ), cost( c ), cvtCost( Cost::zero ), env( std::move( e ) ), open( std::move( o ) ), 
+
+	Candidate(
+		const ast::Expr * x, ast::TypeEnvironment && e, ast::OpenVarSet && o,
+		ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero )
+	: expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ),
 	  need( n.begin(), n.end() ) {}
 };
Index: src/SynTree/Constant.cc
===================================================================
--- src/SynTree/Constant.cc	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/SynTree/Constant.cc	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -22,8 +22,7 @@
 #include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
 
-Constant::Constant( Type * type, std::string rep, unsigned long long val ) : type( type ), rep( rep ), val( val ) {}
-Constant::Constant( Type * type, std::string rep, double val ) : type( type ), rep( rep ), val( val ) {}
+Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {}
 
-Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), val( other.val ) {
+Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) {
 	type = other.type->clone();
 }
@@ -35,8 +34,4 @@
 }
 
-Constant Constant::from_char( char c ) {
-	return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c );
-}
-
 Constant Constant::from_int( int i ) {
 	return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i );
@@ -45,18 +40,4 @@
 Constant Constant::from_ulong( unsigned long i ) {
 	return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i );
-}
-
-Constant Constant::from_double( double d ) {
-	return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );
-}
-
-Constant Constant::from_string( std::string const & str ) {
-	return Constant(
-		new ArrayType(
-			noQualifiers,
-			new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ),
-			new ConstantExpr( Constant::from_int( str.size() + 1 /* \0 */ )),
-			false, false ),
-		std::string("\"") + str + "\"", (unsigned long long int)0 );
 }
 
@@ -74,14 +55,9 @@
 unsigned long long Constant::get_ival() const {
 	assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
-	return val.ival;
-}
-
-double Constant::get_dval() const {
-	assertf( ! strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." );
-	return val.dval;
+	return ival.value();
 }
 
 void Constant::print( std::ostream &os, Indenter ) const {
-	os << "(" << rep << " " << val.ival;
+	os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ;
 	if ( type ) {
 		os << ": ";
Index: src/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision 8b34df032b958bfd4e1d59e5d6573aa153bd4015)
+++ src/SynTree/Constant.h	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -18,4 +18,5 @@
 #include <iosfwd>     // for ostream
 #include <string>     // for string
+#include <optional>   // for optional
 
 #include "BaseSyntaxNode.h"
@@ -27,6 +28,5 @@
 class Constant : public BaseSyntaxNode {
   public:
-	Constant( Type * type, std::string rep, unsigned long long val );
-	Constant( Type * type, std::string rep, double val );
+	Constant( Type * type, std::string rep, std::optional<unsigned long long> i );
 	Constant( const Constant & other );
 	virtual ~Constant();
@@ -39,18 +39,11 @@
 	void set_value( std::string newValue ) { rep = newValue; }
 	unsigned long long get_ival() const;
-	double get_dval() const;
 
 	/// generates a boolean constant of the given bool
 	static Constant from_bool( bool b );
-	/// generates a char constant of the given char
-	static Constant from_char( char c );
 	/// generates an integer constant of the given int
 	static Constant from_int( int i );
 	/// generates an integer constant of the given unsigned long int
 	static Constant from_ulong( unsigned long i );
-	/// generates a floating point constant of the given double
-	static Constant from_double( double d );
-	/// generates an array of chars constant of the given string
-	static Constant from_string( std::string const & s );
 
 	/// generates a null pointer value for the given type. void * if omitted.
@@ -63,10 +56,7 @@
 	Type * type;
 	std::string rep;
-	union Val {
-		unsigned long long ival;
-		double dval;
-		Val( unsigned long long ival ) : ival( ival ) {}
-		Val( double dval ) : dval( dval ) {}
-	} val;
+	std::optional<unsigned long long> ival;
+
+	friend class ConverterOldToNew;
 };
 
Index: src/include/optional
===================================================================
--- src/include/optional	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
+++ src/include/optional	(revision 54b3fde2a9cc874ca7e4fdbdba44e7162a9e2f97)
@@ -0,0 +1,28 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// optional.h --
+//
+// Author           : Michael L. Brooks
+// Created On       : Mon Jun 17 10:05:00 2019
+// Last Modified By : Michael L. Brooks
+// Last Modified On : Mon Jun 17 10:05:00 2019
+// Update Count     : 1
+//
+
+#pragma once
+// Pragmas for header cleanup tool
+// IWYU pragma: private, include <optional>
+
+#if __cplusplus < 201703L
+#include_next <experimental/optional>
+namespace std {
+	using std::experimental::optional;
+	using std::experimental::nullopt;
+}
+#else
+#include_next <optional>
+#endif
