You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by bt...@apache.org on 2019/12/18 18:26:14 UTC

[incubator-daffodil] branch master updated: Add typesafty to our handling of infoset data values.

This is an automated email from the ASF dual-hosted git repository.

btsloane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git


The following commit(s) were added to refs/heads/master by this push:
     new eb7e040  Add typesafty to our handling of infoset data values.
eb7e040 is described below

commit eb7e0403baa097328c7f75eabaef292ac0092bcc
Author: Brandon Sloane <bt...@verizon.net>
AuthorDate: Tue Jul 23 20:14:29 2019 -0400

    Add typesafty to our handling of infoset data values.
    
    For performance reasons, we have been making extensive use of
    AnyRef to store data values in our infoset, and throughout the runtime.
    This allows us to avoid boxing, but prevents the type system from validating
    that unexepected types to not infect our values.
    
    This commit introduces a value type, DataValue, which provides a 0 overhead (eg. no boxing)
    wrapper around AnyRef, while only allowing a limited number of types to populate it.
    
    In doing so, an unrelated bug of mixing Java and Scala BigInts was uncovered and corrected.
    Such a bug should be much less likely to occur in the future.
    
    Due to a bug in Scala 2.11 (https://github.com/scala/bug/issues/7521), we have 2 implementations
    of DataValue. The 2.11 version automatically boxes/unboxes all instances of Array[Byte]
    
    DAFFODIL-2169
---
 .../daffodil/dpath/DFDLExpressionParser.scala      |   2 +-
 .../org/apache/daffodil/dpath/Expression.scala     |  19 +-
 .../apache/daffodil/dsom/CompiledExpression.scala  |   5 +-
 .../org/apache/daffodil/dsom/ElementBase.scala     |  11 +-
 .../org/apache/daffodil/dsom/SimpleTypes.scala     |   7 +-
 .../daffodil/dsom/TestExternalVariablesNew.scala   |   2 +-
 .../daffodil/dsom/TestSimpleTypeUnions.scala       |   8 +-
 .../externalvars/TestExternalVariablesLoader.scala |   6 +-
 .../org/apache/daffodil/infoset/TestInfoset.scala  |  22 +-
 .../daffodil/infoset/TestInfosetCursor.scala       |  42 ++--
 .../infoset/TestInfosetCursorFromReader.scala      |  44 ++--
 .../infoset/TestInfosetCursorFromReader2.scala     |   2 +-
 .../unparsers/BinaryBooleanUnparsers.scala         |   2 +-
 .../unparsers/BinaryNumberUnparsers.scala          |   4 +-
 .../processors/unparsers/BlobLengthUnparser.scala  |   4 +-
 .../unparsers/ConvertBinaryCalendarUnparser.scala  |   2 +-
 .../unparsers/ConvertTextBooleanUnparser.scala     |   2 +-
 .../unparsers/ConvertTextCalendarUnparser.scala    |   2 +-
 .../unparsers/ConvertTextNumberUnparser.scala      |   4 +-
 .../processors/unparsers/ElementUnparser.scala     |   4 +-
 .../unparsers/ExpressionEvaluatingUnparsers.scala  |  33 +--
 .../unparsers/HexBinaryLengthUnparser.scala        |   6 +-
 .../unparsers/PackedBinaryUnparserTraits.scala     |  15 +-
 .../unparsers/SpecifiedLengthUnparsers.scala       |   4 +-
 .../processors/unparsers/ZeroLengthDetector.scala  |   4 +-
 .../org/apache/daffodil/infoset/DataValue.scala    | 253 ++++++++++++++++++++
 .../org/apache/daffodil/infoset/DataValue.scala    | 235 +++++++++++++++++++
 .../org/apache/daffodil/dpath/ComparisonOps.scala  | 166 ++++++-------
 .../org/apache/daffodil/dpath/ConverterOps.scala   | 186 ++++++++-------
 .../org/apache/daffodil/dpath/ConverterOps2.scala  |  25 +-
 .../org/apache/daffodil/dpath/ConverterOps3.scala  |  55 +++--
 .../apache/daffodil/dpath/DFDLConstructors.scala   |  52 +++--
 .../org/apache/daffodil/dpath/DFDLFunctions.scala  |  23 +-
 .../org/apache/daffodil/dpath/DFDLFunctions2.scala |  16 +-
 .../org/apache/daffodil/dpath/DFDLXFunctions.scala |  19 +-
 .../daffodil/dpath/DFDLXTypeCalcFunctions.scala    |  27 +--
 .../scala/org/apache/daffodil/dpath/DPath.scala    |  79 ++++---
 .../org/apache/daffodil/dpath/DPathRuntime.scala   |  41 ++--
 .../scala/org/apache/daffodil/dpath/DState.scala   |  71 +++---
 .../scala/org/apache/daffodil/dpath/FNBases.scala  |  66 +++---
 .../org/apache/daffodil/dpath/FNFunctions.scala    | 257 ++++++++++++---------
 .../org/apache/daffodil/dpath/MATHFunctions.scala  |   8 +-
 .../scala/org/apache/daffodil/dpath/NodeInfo.scala |  58 ++---
 .../daffodil/dpath/SuspendableExpression.scala     |  17 +-
 .../daffodil/dpath/UserDefinedFunctionBase.scala   |   8 +-
 .../org/apache/daffodil/dpath/XSConstructors.scala |  28 ++-
 .../org/apache/daffodil/dpath/XSHexBinary.scala    |   4 +-
 .../apache/daffodil/dsom/CompiledExpression1.scala |  11 +-
 .../org/apache/daffodil/infoset/Infoset.scala      |  15 +-
 .../org/apache/daffodil/infoset/InfosetImpl.scala  | 125 +++++-----
 .../apache/daffodil/processors/Evaluatable.scala   |   2 +
 .../apache/daffodil/processors/RuntimeData.scala   |  76 +++---
 .../daffodil/processors/TypeCalculator.scala       |  38 +--
 .../apache/daffodil/processors/VariableMap1.scala  |  46 ++--
 .../processors/parsers/BinaryNumberTraits.scala    |   2 +-
 .../processors/parsers/ElementKindParsers.scala    |   2 +-
 .../parsers/ExpressionEvaluatingParsers.scala      |  46 ++--
 .../daffodil/processors/parsers/PState.scala       |   3 +-
 .../parsers/SequenceChildParseResultHelper.scala   |   2 +-
 eclipse-projects/runtime1/.classpath               |   1 +
 60 files changed, 1488 insertions(+), 831 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/DFDLExpressionParser.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/DFDLExpressionParser.scala
index dd23028..885f269 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/DFDLExpressionParser.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/DFDLExpressionParser.scala
@@ -61,7 +61,7 @@ class DFDLPathExpressionParser[T <: AnyRef](
     val recipe = tree.compiledDPath // if we cannot get one this will fail by throwing out of here.
 
     val value = recipe.runExpressionForConstant(context.schemaFileLocation, context, host.tunable)
-    val res: CompiledExpression[T] = value match {
+    val res: CompiledExpression[T] = value.getOptionAnyRef match {
       case Some(constantValue) => {
         Assert.invariant(constantValue != null)
         val res = new ConstantExpression[T](qn, nodeInfoKind, constantValue.asInstanceOf[T])
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
index fcf666f..83da2c2 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
@@ -26,13 +26,15 @@ import org.apache.daffodil.xml.RefQName
 import scala.util.{ Success, Failure }
 import org.apache.daffodil.dsom.RelativePathPastRootError
 import org.apache.daffodil.equality._
-import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
+import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt}
+import java.lang.{ Long => JLong, Integer => JInt, Boolean => JBoolean, Double => JDouble }
 import org.apache.daffodil.util.Numbers
 import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.infoset.NoNextElement
 import org.apache.daffodil.infoset.OnlyOnePossibilityForNextElement
 import org.apache.daffodil.infoset.SeveralPossibilitiesForNextElement
 import org.apache.daffodil.util.LogLevel
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 import org.apache.daffodil.udf.UserDefinedFunctionService
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.BasicComponent
@@ -1333,7 +1335,7 @@ abstract class LiteralExpressionBase(value: Any)
    * Convert to regular types from the pessimistic BigInt
    * and BigDecimal that come in from the parser.
    */
-  lazy val litValue = value match {
+  lazy val litValue:DataValuePrimitive = value match {
     case s: String => s
     case i: Int => i
     case i: BigInt => {
@@ -1367,20 +1369,21 @@ abstract class LiteralExpressionBase(value: Any)
   }
 
   override lazy val compiledDPath: CompiledDPath = {
-    new CompiledDPath(Literal(Numbers.asAnyRef(litValue)) +: conversions)
+    litValue
+    new CompiledDPath(Literal(litValue) +: conversions)
   }
 
   override lazy val inherentType = {
-    litValue match {
+    litValue.getAnyRef match {
       case s: String => NodeInfo.String
       case i: BigInt => Assert.usageError("Expected java.math.BigInteger but got BigInt.")
       case i: JBigInt => NodeInfo.Integer
       case d: BigDecimal => Assert.usageError("Expected java.math.BigDecimal but got package.BigDecimal.")
       case d: JBigDecimal => NodeInfo.Decimal
-      case df: Double => NodeInfo.Double
-      case l: Long => NodeInfo.Long
-      case i: Int => NodeInfo.Int
-      case b: Boolean => NodeInfo.Boolean
+      case df: JDouble => NodeInfo.Double
+      case l: JLong => NodeInfo.Long
+      case i: JInt => NodeInfo.Int
+      case b: JBoolean => NodeInfo.Boolean
       case _ => Assert.invariantFailed("value not one of the expected types " + litValue.getClass())
     }
   }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/CompiledExpression.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/CompiledExpression.scala
index e6f82bc..5f6d746 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/CompiledExpression.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/CompiledExpression.scala
@@ -24,6 +24,7 @@ import org.apache.daffodil.xml.NamedQName
 import java.lang.{ Long => JLong, Boolean => JBoolean }
 import org.apache.daffodil.schema.annotation.props.Found
 import org.apache.daffodil.oolag.OOLAG._
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 import org.apache.daffodil.processors.HasTunable
 import org.apache.daffodil.BasicComponent
 
@@ -245,7 +246,7 @@ class ExpressionCompiler[T <: AnyRef] extends ExpressionCompilerBase[T] {
       if (exprOrLiteral.startsWith("{{")) exprOrLiteral.tail
       else exprOrLiteral
 
-    val logical = try {
+    val logical:DataValuePrimitive = try {
       maybePrimType.get.fromXMLString(literal)
     } catch {
       case e: Exception => {
@@ -254,6 +255,6 @@ class ExpressionCompiler[T <: AnyRef] extends ExpressionCompilerBase[T] {
       }
     }
 
-    new ConstantExpression[T](qn, nodeInfoKind, logical.asInstanceOf[T])
+    new ConstantExpression[T](qn, nodeInfoKind, logical.getAnyRef.asInstanceOf[T])
   }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index a0b6fd6..08a78b9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -34,6 +34,9 @@ import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.api.WarnID
 import java.lang.{ Integer => JInt }
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveOrUseNilForDefaultOrNull
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveOrUseNilForDefaultOrNull
 
 /**
  * Note about DSOM design versus say XSOM or Apache XSD library.
@@ -327,11 +330,11 @@ trait ElementBase
    * nor any PUA-remapped characters. This insures the default/fixed value can still be
    * used for ordinary XML-schema validation outside of Daffodil/DFDL.
    */
-  final lazy val defaultValue: Option[AnyRef] = {
+  final lazy val defaultValue: DataValuePrimitiveOrUseNilForDefaultOrNull = {
     if (isDefaultable && (isScalar || isArraywithAtLeastOneRequiredArrayElement)) {
       val dv =
         if (isNillable && useNilForDefault =:= YesNo.Yes) {
-          Some(UseNilForDefault) // singleton object indicator
+          DataValue.UseNilForDefault
         } else {
           //
           // Note: no remapping PUA chars or otherwise messing with the text of the default value
@@ -342,8 +345,8 @@ trait ElementBase
           val value = primType.fromXMLString(str)
           value
         }
-      Some(dv)
-    } else None
+      dv
+    } else DataValue.NoValue
   }
 
   lazy val unparserInfosetElementDefaultingBehavior: UnparserInfo.InfosetEventBehavior = {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SimpleTypes.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SimpleTypes.scala
index bab02ad..d80245d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SimpleTypes.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SimpleTypes.scala
@@ -51,6 +51,7 @@ import org.apache.daffodil.xml.NS
 import org.apache.daffodil.exceptions.SchemaFileLocation
 import org.apache.daffodil.cookers.IntRangeCooker
 import org.apache.daffodil.util.RangeBound
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 
 trait TypeBase {
   def optRestriction: Option[Restriction] = None
@@ -333,7 +334,7 @@ abstract class SimpleTypeDefBase(xml: Node, lexicalParent: SchemaComponent)
           if (enumerations.size != restriction.enumerations.size) {
             SDE("If one enumeration value defines a repValue, then all must define a repValue")
           }
-          val terms = enumerations.map(enum => (enum.optRepValueSet.get, enum.canonicalRepValue.get, enum.enumValueCooked))
+          val terms = enumerations.map(enum => (enum.optRepValueSet.get, enum.canonicalRepValue.get, enum.enumValueCooked.getAnyRef))
           Some(TypeCalculatorCompiler.compileKeysetValue(terms, srcType, dstType))
         }
       })
@@ -564,10 +565,10 @@ final class EnumerationDefFactory(
   override lazy val optRepType = parentType.optRepType
 
   lazy val enumValueRaw: String = (xml \ "@value").head.text
-  lazy val enumValueCooked: AnyRef = parentType.primType.fromXMLString(enumValueRaw)
+  lazy val enumValueCooked: DataValuePrimitive = parentType.primType.fromXMLString(enumValueRaw)
 
   override lazy val optRepValueSet: Option[RepValueSet[AnyRef]] = optRepValueSetFromAttribute
-  lazy val logicalValueSet: RepValueSet[AnyRef] = RepValueSetCompiler.compile(Seq(enumValueCooked), Seq())
+  lazy val logicalValueSet: RepValueSet[AnyRef] = RepValueSetCompiler.compile(Seq(enumValueCooked.getAnyRef), Seq())
   lazy val canonicalRepValue: Option[AnyRef] = {
     val ans1 = repValuesAttrCooked.headOption
     val ans2 = repValueRangesAttrCooked.headOption.map(_._1).flatMap(asBound => {
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestExternalVariablesNew.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestExternalVariablesNew.scala
index f3a8e9c..c9de89a 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestExternalVariablesNew.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestExternalVariablesNew.scala
@@ -140,7 +140,7 @@ class TestExternalVariablesNew {
       case Success(None) => fail("Did not find " + keyToFind + " in the VariableMap.")
       case Success(Some(variab)) => {
         // Found var1 but is the value correct?
-        assertTrue(variab.toString.contains("Variable(VariableDefined,One(" + expectedValue + ")"))
+        assertTrue(variab.toString.contains("Variable(VariableDefined,DataValue(" + expectedValue + ")"))
       }
     }
   }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestSimpleTypeUnions.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestSimpleTypeUnions.scala
index 4a472e4..202d0f6 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestSimpleTypeUnions.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestSimpleTypeUnions.scala
@@ -108,7 +108,7 @@ class TestSimpleTypeUnions {
   @Test def testUnionNoUnionMemberOK {
     val (result, _) = TestUtils.testString(testSchema1, "3")
     val i = result.resultState.asInstanceOf[PState].infoset.asInstanceOf[DIDocument].root.asInstanceOf[DISimple]
-    val Some(dv: java.lang.Integer) = Some(i.dataValue)
+    val Some(dv: java.lang.Integer) = Some(i.dataValue.getInt)
     assertEquals(3, dv.intValue())
     assertTrue(i.unionMemberRuntimeData.isEmpty)
     assertFalse(i.valid.get)
@@ -185,7 +185,7 @@ class TestSimpleTypeUnions {
   @Test def testUnionNot3 {
     val (result, _) = TestUtils.testString(testSchema2, "3")
     val i = result.resultState.asInstanceOf[PState].infoset.asInstanceOf[DIDocument].root.asInstanceOf[DISimple]
-    val Some(dv: java.lang.Integer) = Some(i.dataValue)
+    val Some(dv: java.lang.Integer) = Some(i.dataValue.getInt)
     assertEquals(3, dv.intValue())
     assertTrue(i.unionMemberRuntimeData.isEmpty)
     assertFalse(i.valid.get)
@@ -306,7 +306,7 @@ class TestSimpleTypeUnions {
   @Test def testRestrictionOnUnionFail_01 {
     val (result, _) = TestUtils.testString(testSchema3, "foo4bar")
     val i = result.resultState.asInstanceOf[PState].infoset.asInstanceOf[DIDocument].root.asInstanceOf[DISimple]
-    val Some(dv: String) = Some(i.dataValue)
+    val Some(dv: String) = Some(i.dataValue.getString)
     assertEquals("foo4bar", dv)
     assertTrue(i.unionMemberRuntimeData.isEmpty)
     assertFalse(i.valid.get)
@@ -335,7 +335,7 @@ class TestSimpleTypeUnions {
   @Test def testRestrictionOnUnionFail_02 {
     val (result, _) = TestUtils.testString(testSchema3, "notfoo1bar")
     val i = result.resultState.asInstanceOf[PState].infoset.asInstanceOf[DIDocument].root.asInstanceOf[DISimple]
-    val Some(dv: String) = Some(i.dataValue)
+    val Some(dv: String) = Some(i.dataValue.getString)
     assertEquals("notfoo1bar", dv)
     assertTrue(i.unionMemberRuntimeData.isEmpty)
     assertFalse(i.valid.get)
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/externalvars/TestExternalVariablesLoader.scala b/daffodil-core/src/test/scala/org/apache/daffodil/externalvars/TestExternalVariablesLoader.scala
index b20eb2d..335fae6 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/externalvars/TestExternalVariablesLoader.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/externalvars/TestExternalVariablesLoader.scala
@@ -103,16 +103,16 @@ class TestExternalVariablesLoader extends Logging {
 
     // Verify that v_with_default is defined and is 42.
     assertTrue(var_v_with_default.value.isDefined)
-    assertEquals("42", var_v_with_default.value.get.toString())
+    assertEquals("42", var_v_with_default.value.getAnyRef.toString())
 
     val vmap = ExternalVariablesLoader.loadVariables(extVarFile1, sd, initialVMap, tunable)
 
     // Verify that the external variables override the previous values
     // in the VariableMap
     val (value1, _) = vmap.readVariable(v_no_default_vrd, Fakes.fakeElem)
-    assertEquals(1, value1)
+    assertEquals(1, value1.getAnyRef)
     val (value2, _) = vmap.readVariable(v_with_default_vrd, Fakes.fakeElem)
-    assertEquals(2, value2)
+    assertEquals(2, value2.getAnyRef)
   }
 
   @Test def test_ext_var_not_match_defined_var() = {
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfoset.scala b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfoset.scala
index 6fa9812..0cbec57 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfoset.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfoset.scala
@@ -125,7 +125,7 @@ class TestInfoset1 {
     val Seq(w_erd) = list_erd.childERDs
     val wItem = infoset.getChild(w_erd, tunable).asInstanceOf[InfosetSimpleElement]
     assertEquals(infoset, wItem.parent)
-    assertEquals(4, wItem.dataValue)
+    assertEquals(4, wItem.dataValue.getAnyRef)
 
   }
 
@@ -152,9 +152,9 @@ class TestInfoset1 {
     val Seq(w_erd, _, _, c_erd) = list_erd.childERDs
     assertEquals(list_erd, infoset.runtimeData)
     val wItem = infoset.asComplex.getChild(w_erd, tunable).asInstanceOf[InfosetSimpleElement]
-    assertEquals(4, wItem.dataValue)
+    assertEquals(4, wItem.dataValue.getAnyRef)
     val cItem = infoset.asComplex.getChild(c_erd, tunable).asInstanceOf[InfosetSimpleElement]
-    assertEquals(7, cItem.dataValue)
+    assertEquals(7, cItem.dataValue.getAnyRef)
     assertEquals(infoset, cItem.parent)
   }
 
@@ -178,10 +178,10 @@ class TestInfoset1 {
         var a = arr(1).asInstanceOf[InfosetSimpleElement]
         assertEquals(w_erd, a.runtimeData)
 
-        assertEquals(4, a.dataValue)
+        assertEquals(4, a.dataValue.getAnyRef)
         assertEquals(infoset, a.parent)
         a = arr(2).asInstanceOf[InfosetSimpleElement] // 1-based
-        assertEquals(5, a.dataValue)
+        assertEquals(5, a.dataValue.getAnyRef)
         assertEquals(infoset, a.parent)
       }
     }
@@ -213,15 +213,15 @@ class TestInfoset1 {
         var a = arr(1).asInstanceOf[InfosetSimpleElement]
         assertEquals(2, arr.length)
         assertEquals(w_erd, a.runtimeData)
-        assertEquals(4, a.dataValue)
+        assertEquals(4, a.dataValue.getAnyRef)
         assertEquals(infoset, a.parent)
         a = arr(2).asInstanceOf[InfosetSimpleElement] // 1-based
-        assertEquals(5, a.dataValue)
+        assertEquals(5, a.dataValue.getAnyRef)
         assertEquals(infoset, a.parent)
       }
     }
     infoset.getChild(c_erd, tunable) match {
-      case s: DISimple => assertEquals(7, s.dataValue)
+      case s: DISimple => assertEquals(7, s.dataValue.getAnyRef)
     }
   }
 
@@ -327,7 +327,7 @@ class TestInfoset1 {
         xa = arr(2).asInstanceOf[InfosetComplexElement] // 1-based
         val c = xa.getChild(c_erd, tunable)
         c match {
-          case c: DISimple => assertEquals(7, c.dataValue)
+          case c: DISimple => assertEquals(7, c.dataValue.getAnyRef)
         }
       }
     }
@@ -376,12 +376,12 @@ class TestInfoset1 {
         assertEquals(x_erd, xa.runtimeData)
         val c = xa.getChild(c_erd, tunable)
         c match {
-          case c: DISimple => assertEquals(7, c.dataValue)
+          case c: DISimple => assertEquals(7, c.dataValue.getAnyRef)
         }
         xa = arr(2).asInstanceOf[InfosetComplexElement]
         val b = xa.getChild(b_erd, tunable)
         b match {
-          case c: DISimple => assertEquals(8, c.dataValue)
+          case c: DISimple => assertEquals(8, c.dataValue.getAnyRef)
         }
       }
     }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursor.scala b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursor.scala
index ff8c953..1f6c596 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursor.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursor.scala
@@ -177,7 +177,7 @@ class TestInfosetInputter {
     ic.pushTRD(fooERD)
     assertTrue(ic.advance)
     val Start(foo: DISimple) = aacc
-    assertEquals("Hello", foo.dataValue)
+    assertEquals("Hello", foo.dataValue.getAnyRef)
 
     assertTrue(ic.inspect)
     val End(ifoo: DISimple) = iacc
@@ -237,9 +237,9 @@ class TestInfosetInputter {
     assertFalse(ic.inspect)
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_s eq foo_e)
-    assertTrue(foo_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_s.dataValueAsString =:= "Hello")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "World")
   }
 
@@ -315,15 +315,15 @@ class TestInfosetInputter {
     assertFalse(ic.inspect)
     assertTrue(bar1_s eq bar1_e) // exact same object
     assertTrue(foo1_s eq foo1_e)
-    assertTrue(foo1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo1_s.dataValueAsString =:= "Hello")
-    assertTrue(baz1_s.dataValue.isInstanceOf[String])
+    assertTrue(baz1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz1_s.dataValueAsString =:= "World")
     assertTrue(bar2_s eq bar2_e) // exact same object
     assertTrue(foo2_s eq foo2_e)
-    assertTrue(foo2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo2_s.dataValueAsString =:= "Hello")
-    assertTrue(baz2_s.dataValue.isInstanceOf[String])
+    assertTrue(baz2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz2_s.dataValueAsString =:= "World")
     assertTrue(quux_s eq quux_e)
   }
@@ -363,10 +363,10 @@ class TestInfosetInputter {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
   }
 
@@ -409,12 +409,12 @@ class TestInfosetInputter {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -459,12 +459,12 @@ class TestInfosetInputter {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -512,12 +512,12 @@ class TestInfosetInputter {
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(baz_arr_s eq baz_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -561,7 +561,7 @@ class TestInfosetInputter {
     assertTrue(bar_s1 eq bar_e1) // exact same object
     assertTrue(foo_s1 eq foo_s2)
     assertTrue(foo_s1 eq foo_e)
-    assertTrue(foo_s1.dataValue.isInstanceOf[String])
+    assertTrue(foo_s1.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_s1.dataValueAsString =:= "Hello")
   }
 
@@ -614,9 +614,9 @@ class TestInfosetInputter {
     assertFalse(ic.inspect)
     assertTrue(as eq ase) // exact same object
     assertTrue(e eq ee)
-    assertTrue(c1.dataValue.isInstanceOf[String])
+    assertTrue(c1.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(c1.dataValueAsString =:= "Hello")
-    assertTrue(c2.dataValue.isInstanceOf[String])
+    assertTrue(c2.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(c2.dataValueAsString =:= "World")
   }
 
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader.scala b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader.scala
index 2b7128f..cc7c0b5 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader.scala
@@ -80,7 +80,7 @@ class TestInfosetInputterFromReader {
     val is = ii.toStream.toList
     val List(Start(s: DISimple), End(e: DISimple)) = is
     assertTrue(s eq e) // exact same object
-    assertTrue(s.dataValue.isInstanceOf[String])
+    assertTrue(s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(s.dataValueAsString =:= "Hello")
   }
 
@@ -123,7 +123,7 @@ class TestInfosetInputterFromReader {
     assertFalse(is.hasNext)
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_s eq foo_e)
-    assertTrue(foo_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_s.dataValueAsString =:= "Hello")
   }
 
@@ -155,9 +155,9 @@ class TestInfosetInputterFromReader {
     assertFalse(is.hasNext)
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_s eq foo_e)
-    assertTrue(foo_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_s.dataValueAsString =:= "Hello")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "World")
   }
 
@@ -249,15 +249,15 @@ class TestInfosetInputterFromReader {
     assertFalse(is.hasNext)
     assertTrue(bar1_s eq bar1_e) // exact same object
     assertTrue(foo1_s eq foo1_e)
-    assertTrue(foo1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo1_s.dataValueAsString =:= "Hello")
-    assertTrue(baz1_s.dataValue.isInstanceOf[String])
+    assertTrue(baz1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz1_s.dataValueAsString =:= "World")
     assertTrue(bar2_s eq bar2_e) // exact same object
     assertTrue(foo2_s eq foo2_e)
-    assertTrue(foo2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo2_s.dataValueAsString =:= "Hello")
-    assertTrue(baz2_s.dataValue.isInstanceOf[String])
+    assertTrue(baz2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz2_s.dataValueAsString =:= "World")
     assertTrue(quux_s eq quux_e)
   }
@@ -297,10 +297,10 @@ class TestInfosetInputterFromReader {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
   }
 
@@ -345,12 +345,12 @@ class TestInfosetInputterFromReader {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -395,12 +395,12 @@ class TestInfosetInputterFromReader {
     assertTrue(bar_s eq bar_e) // exact same object
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -442,12 +442,12 @@ class TestInfosetInputterFromReader {
     assertTrue(foo_arr_s eq foo_arr_e)
     assertTrue(baz_arr_s eq baz_arr_e)
     assertTrue(foo_1_s eq foo_1_e)
-    assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_1_s.dataValueAsString =:= "Hello")
     assertTrue(foo_2_s eq foo_2_e)
-    assertTrue(foo_2_s.dataValue.isInstanceOf[String])
+    assertTrue(foo_2_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_2_s.dataValueAsString =:= "World")
-    assertTrue(baz_s.dataValue.isInstanceOf[String])
+    assertTrue(baz_s.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(baz_s.dataValueAsString =:= "Yadda")
   }
 
@@ -486,7 +486,7 @@ class TestInfosetInputterFromReader {
     assertTrue(bar_s1 eq bar_e1) // exact same object
     assertTrue(foo_s1 eq foo_s2)
     assertTrue(foo_s1 eq foo_e)
-    assertTrue(foo_s1.dataValue.isInstanceOf[String])
+    assertTrue(foo_s1.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(foo_s1.dataValueAsString =:= "Hello")
   }
 
@@ -538,9 +538,9 @@ class TestInfosetInputterFromReader {
     assertFalse(is.hasNext)
     assertTrue(as eq ase) // exact same object
     assertTrue(e eq ee)
-    assertTrue(c1.dataValue.isInstanceOf[String])
+    assertTrue(c1.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(c1.dataValueAsString =:= "Hello")
-    assertTrue(c2.dataValue.isInstanceOf[String])
+    assertTrue(c2.dataValue.getAnyRef.isInstanceOf[String])
     assertTrue(c2.dataValueAsString =:= "World")
   }
 }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader2.scala b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader2.scala
index 3d62d3b..61ddbc1 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader2.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/infoset/TestInfosetCursorFromReader2.scala
@@ -108,7 +108,7 @@ class TestInfosetInputterFromReader2 {
       val Start(foo_1_s: DISimple) = is.next
       val End(foo_1_e: DISimple) = is.next
       assertTrue(foo_1_s eq foo_1_e)
-      assertTrue(foo_1_s.dataValue.isInstanceOf[String])
+      assertTrue(foo_1_s.dataValue.getAnyRef.isInstanceOf[String])
       assertEquals("Hello", foo_1_s.dataValueAsString)
     }
     val EndArray(foo_arr_e) = is.next
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryBooleanUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryBooleanUnparsers.scala
index d053196..7aaf9e5 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryBooleanUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryBooleanUnparsers.scala
@@ -54,7 +54,7 @@ abstract class BinaryBooleanUnparserBase(
   def unparse(state: UState): Unit = {
     val nBits = getBitLength(state)
     val node = state.currentInfosetNode.asSimple
-    val value = node.dataValue.asInstanceOf[JBoolean]
+    val value = node.dataValue.getBoolean
     val dos = state.dataOutputStream
 
     if (nBits < 1 || nBits > 32) {
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryNumberUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryNumberUnparsers.scala
index 10192b1..a644e9c 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryNumberUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BinaryNumberUnparsers.scala
@@ -42,7 +42,7 @@ abstract class BinaryNumberBaseUnparser(override val context: ElementRuntimeData
 
   protected def getNumberToPut(state: UState): JNumber = {
     val node = state.currentInfosetNode.asSimple
-    node.dataValue.asInstanceOf[JNumber]
+    node.dataValue.getNumber
   }
 
   protected def getBitLength(s: ParseOrUnparseState): Int
@@ -204,7 +204,7 @@ abstract class BinaryDecimalUnparserBase(e: ElementRuntimeData, signed: YesNo, b
 
   override def getNumberToPut(state: UState): JNumber = {
     val node = state.currentInfosetNode.asSimple
-    val value = node.dataValue.asInstanceOf[JNumber]
+    val value = node.dataValue.getNumber
 
     // We want to scale the bigInt by binaryDecimalVirtualPoint so that it is a BigInt
     val bigDec = asBigDecimal(value)
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BlobLengthUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BlobLengthUnparser.scala
index e5c0238..b97df80 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BlobLengthUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/BlobLengthUnparser.scala
@@ -38,7 +38,7 @@ abstract class BlobUnparserBase(override val context: ElementRuntimeData)
   override def unparse(state: UState): Unit = {
 
     val node = state.currentInfosetNode.asSimple
-    val value = node.dataValue.asInstanceOf[URI]
+    val value = node.dataValue.getURI
     val lengthInBits = getLengthInBits(state)
 
     val lengthInBytes = (lengthInBits + 7) / 8
@@ -101,7 +101,7 @@ final class BlobSpecifiedLengthUnparser(erd: ElementRuntimeData, val lengthEv: U
       lengthEv.evaluate(state).getULong.toLong
     } catch {
       case e: RetryableException => {
-        val uri = state.currentInfosetNode.asSimple.dataValue.asInstanceOf[URI]
+        val uri = state.currentInfosetNode.asSimple.dataValue.getURI
         val path = Paths.get(uri)
         val len = Files.size(path) * 8
         len
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala
index 0c1ec4b..d675af4 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala
@@ -49,7 +49,7 @@ case class ConvertBinaryCalendarSecMilliUnparser(
 
     val node = state.currentInfosetNode.asSimple
 
-    val calValue = node.dataValue match {
+    val calValue = node.dataValue.getAnyRef match {
       case dc: DFDLCalendar => dc.calendar
       case x => Assert.invariantFailed("ConvertBinaryCalendar received unsupported type. %s of type %s.".format(x, Misc.getNameFromClass(x)))
     }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextBooleanUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextBooleanUnparser.scala
index a0730f6..05e2888 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextBooleanUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextBooleanUnparser.scala
@@ -38,7 +38,7 @@ case class ConvertTextBooleanUnparser(
 
     val node = state.currentInfosetNode.asSimple
 
-    val boolValue = node.dataValue match {
+    val boolValue = node.dataValue.getAnyRef match {
       case JTrue => {
         val textBooleanTrueReps: List[String] = textBooleanTrueRepEv.evaluate(state)
         Assert.invariant(textBooleanTrueReps.length >= 1)
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala
index 3636cb7..a8eae2f 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala
@@ -47,7 +47,7 @@ case class ConvertTextCalendarUnparser(
 
     val dc = node.dataValue
 
-    val infosetCalendar = node.dataValue match {
+    val infosetCalendar = node.dataValue.getAnyRef match {
       case dc: DFDLCalendar => dc.calendar
       case x => Assert.invariantFailed("ConvertTextCalendar received unsupported type. %s of type %s.".format(x, Misc.getNameFromClass(x)))
     }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextNumberUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextNumberUnparser.scala
index 9db6482..075a5d2 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextNumberUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextNumberUnparser.scala
@@ -76,7 +76,7 @@ case class ConvertTextNumberUnparser[S](
     val df = nff.getNumFormat(state).get
     val dfs = df.getDecimalFormatSymbols
 
-    val strRep = value match {
+    val strRep = value.getAnyRef match {
       case n: Number if n == 0 && zeroRep.isDefined => zeroRep.get
       // We need to special case infinity and NaN because ICU4J has a bug and
       // will add an exponent to inf/nan (e.g. INFx10^0) if defined in the
@@ -98,7 +98,7 @@ case class ConvertTextNumberUnparser[S](
       case bi: scala.math.BigInt => Assert.usageError("Received scala.math.BigInt, expected java.math.BigInteger.")
       case _ =>
         try {
-          df.format(value)
+          df.format(value.getAnyRef)
         } catch {
           case e: java.lang.ArithmeticException => UE(state, "Unable to format number to pattern: %s", e.getMessage())
         }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
index 956cfd8..2bd7785 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
@@ -30,7 +30,7 @@ import org.apache.daffodil.processors.Evaluatable
 import org.apache.daffodil.infoset.RetryableException
 import org.apache.daffodil.processors.TypeCalculator
 import org.apache.daffodil.util.MaybeBoolean
-
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 /**
  * Elements that, when unparsing, have no length specified.
  *
@@ -320,7 +320,7 @@ class ElementOVCSpecifiedLengthUnparserSuspendableExpresion(
 
   override lazy val expr = rd.outputValueCalcExpr.get
 
-  override final protected def processExpressionResult(state: UState, v: AnyRef) {
+  override final protected def processExpressionResult(state: UState, v: DataValuePrimitive) {
     val diSimple = state.currentInfosetNode.asSimple
 
     diSimple.setDataValue(v)
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
index 50ffbab..5ee6d19 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
@@ -17,20 +17,23 @@
 
 package org.apache.daffodil.processors.unparsers
 
-import org.apache.daffodil.dsom.CompiledExpression
-import org.apache.daffodil.processors.NonTermRuntimeData
-import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.dpath.SuspendableExpression
-import org.apache.daffodil.util.MaybeULong
-import org.apache.daffodil.processors.RuntimeData
+import org.apache.daffodil.dsom.CompiledExpression
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
+import org.apache.daffodil.infoset.Infoset
 import org.apache.daffodil.processors.ElementRuntimeData
 import org.apache.daffodil.processors.Evaluatable
-import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors.NonTermRuntimeData
+import org.apache.daffodil.processors.RuntimeData
+import org.apache.daffodil.processors.Success
 import org.apache.daffodil.processors.TypeCalculator
+import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.processors.Success
-import org.apache.daffodil.infoset.Infoset
-import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.util.MaybeULong
 
 final class SetVariableSuspendableExpression(
   override val expr: CompiledExpression[AnyRef],
@@ -38,7 +41,7 @@ final class SetVariableSuspendableExpression(
   referencingContext: NonTermRuntimeData)
   extends SuspendableExpression {
 
-  override protected def processExpressionResult(ustate: UState, v: AnyRef) {
+  override protected def processExpressionResult(ustate: UState, v: DataValuePrimitive) {
     val newVMap =
       ustate.variableMap.setVariable(rd, v, referencingContext, ustate)
 
@@ -121,9 +124,13 @@ class TypeValueCalcUnparser(typeCalculator: TypeCalculator[AnyRef, AnyRef], repT
 
     val currentSimple = ustate.currentInfosetNode.asSimple
 
-    val logicalValue: AnyRef = currentSimple.dataValue
+    val logicalValue: DataValuePrimitiveNullable = currentSimple.dataValue
+    Assert.invariant(logicalValue.isDefined)
     val logicalValueType = currentSimple.erd.optPrimType.get
-    val repTypeValue: Maybe[AnyRef] = typeCalculator.outputTypeCalcUnparse(ustate, e, logicalValue, logicalValueType)
+    val repTypeValue: DataValuePrimitiveNullable = {
+      val ans = typeCalculator.outputTypeCalcUnparse(ustate, e, logicalValue.getAnyRef, logicalValueType)
+      DataValue.unsafeFromMaybeAnyRef(ans)
+    }
 
     val origInfosetElement = ustate.currentInfosetNode
     val tmpInfosetElement = Infoset.newElement(repTypeRuntimeData).asInstanceOf[DISimple]
@@ -131,7 +138,7 @@ class TypeValueCalcUnparser(typeCalculator: TypeCalculator[AnyRef, AnyRef], repT
     if (ustate.processorStatus == Success) {
 
       Assert.invariant(repTypeValue.isDefined)
-      tmpInfosetElement.setDataValue(repTypeValue.get)
+      tmpInfosetElement.setDataValue(repTypeValue)
       ustate.currentInfosetNodeStack.push(Maybe(tmpInfosetElement))
       repTypeUnparser.unparse1(ustate)
       ustate.currentInfosetNodeStack.pop
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HexBinaryLengthUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HexBinaryLengthUnparser.scala
index d308d93..b3d37d1 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HexBinaryLengthUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HexBinaryLengthUnparser.scala
@@ -40,7 +40,7 @@ abstract class HexBinaryUnparserBase(override val context: ElementRuntimeData)
   override def unparse(state: UState): Unit = {
 
     val node = state.currentInfosetNode.asSimple
-    val value = node.dataValue.asInstanceOf[Array[Byte]]
+    val value = node.dataValue.getByteArray
     val lengthInBits = getLengthInBits(state)
 
     val lengthInBytes = (lengthInBits + 7) / 8
@@ -84,7 +84,7 @@ class HexBinaryMinLengthInBytesUnparser(minLengthInBytes: Long, erd: ElementRunt
   extends HexBinaryUnparserBase(erd) {
 
   override def getLengthInBits(state: UState): Long = {
-    val len = state.currentNode.get.asSimple.dataValue.asInstanceOf[Array[Byte]].length * 8
+    val len = state.currentNode.get.asSimple.dataValue.getByteArray.length * 8
     val min = minLengthInBytes * 8
     scala.math.max(len, min)
   }
@@ -98,7 +98,7 @@ final class HexBinarySpecifiedLengthUnparser(erd: ElementRuntimeData, val length
       lengthEv.evaluate(state).getULong.toLong
     } catch {
       case e: RetryableException => {
-        val bytes = state.currentInfosetNode.asSimple.dataValue.asInstanceOf[Array[Byte]]
+        val bytes = state.currentInfosetNode.asSimple.dataValue.getByteArray
         val len = bytes.length * 8
         len
       }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/PackedBinaryUnparserTraits.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/PackedBinaryUnparserTraits.scala
index 39200c5..1a4969b 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/PackedBinaryUnparserTraits.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/PackedBinaryUnparserTraits.scala
@@ -32,6 +32,7 @@ import org.apache.daffodil.processors.ParseOrUnparseState
 import org.apache.daffodil.processors.Processor
 import org.apache.daffodil.schema.annotation.props.gen.LengthUnits
 import org.apache.daffodil.util.Maybe._
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 
 trait PackedBinaryConversion {
   def fromBigInteger(bigInt: JBigInteger, nBits: Int): Array[Byte]
@@ -47,7 +48,7 @@ abstract class PackedBinaryBaseUnparser(
   protected def getBitLength(s: ParseOrUnparseState): Int
 
   def putNumber(dos: DataOutputStream, number: JNumber, nBits: Int, finfo: FormatInfo): Boolean
-  
+
   def getNumberToPut(state: UState): JNumber = {
     val node = state.currentInfosetNode.asSimple
 
@@ -55,13 +56,13 @@ abstract class PackedBinaryBaseUnparser(
     //   - using dataValue would give the Calendar value rather than that string. Since the Calendar value
     //   cannot be cast as a JNumber we need to use dataValueAsString and convert it to a JBigInteger.
     //   With packed numbers, dataValue is already a number so just use that.
-    val nodeValue =
+    val nodeValue: DataValuePrimitiveNullable =
       node.erd.optPrimType.get match {
-      case NodeInfo.Date | NodeInfo.DateTime | NodeInfo.Time => new JBigInteger(node.dataValueAsString)
-      case _ => node.dataValue
-    }
+        case NodeInfo.Date | NodeInfo.DateTime | NodeInfo.Time => new JBigInteger(node.dataValueAsString)
+        case _ => node.dataValue
+      }
 
-    val value = nodeValue.asInstanceOf[JNumber]
+    val value = nodeValue.getNumber
     value
   }
 
@@ -104,7 +105,7 @@ abstract class PackedBinaryIntegerBaseUnparser(
   e: ElementRuntimeData)
   extends PackedBinaryBaseUnparser(e) {
 
-  override def getNumberToPut(ustate: UState): JNumber = { 
+  override def getNumberToPut(ustate: UState): JNumber = {
     val number = super.getNumberToPut(ustate)
     val bigInt = number.isInstanceOf[JBigInteger] match {
       case true => number.asInstanceOf[JBigInteger]
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
index edf3117..7670a71 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
@@ -118,7 +118,7 @@ final class SpecifiedLengthExplicitImplicitUnparser(
       //
       if (areTruncating) {
         val diSimple = state.currentInfosetNode.asSimple
-        val v = diSimple.dataValue.asInstanceOf[String]
+        val v = diSimple.dataValue.getString
         val tl = maybeTLBits.get
         val cs = getCharset(state)
         val newV = state.truncateToBits(v, cs, tl)
@@ -179,7 +179,7 @@ final class SpecifiedLengthExplicitImplicitUnparser(
       //
       if (areTruncating) {
         val diSimple = state.currentInfosetNode.asSimple
-        val v = diSimple.dataValue.asInstanceOf[String]
+        val v = diSimple.dataValue.getString
         val tl = tlChars.get
         if (v.length > tl) {
           // string is too long, truncate to target length
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala
index 66d69e2..a2d6f12 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala
@@ -172,7 +172,7 @@ sealed trait HexBinaryZeroLengthMixin { self: ZeroLengthDetector =>
       } else {
         diElement match {
           case st: DISimple => {
-            val arr = st.dataValue.asInstanceOf[Array[Byte]]
+            val arr = st.dataValue.getByteArray
             val len = arr.length
             len > 0
           }
@@ -191,7 +191,7 @@ sealed trait HexBinaryZeroLengthMixin { self: ZeroLengthDetector =>
       else {
         diElement match {
           case st: DISimple => {
-            val arr = st.dataValue.asInstanceOf[Array[Byte]]
+            val arr = st.dataValue.getByteArray
             val len = arr.length
             len == 0
           }
diff --git a/daffodil-runtime1/src/main/scala-2.11/org/apache/daffodil/infoset/DataValue.scala b/daffodil-runtime1/src/main/scala-2.11/org/apache/daffodil/infoset/DataValue.scala
new file mode 100644
index 0000000..84bbf93
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala-2.11/org/apache/daffodil/infoset/DataValue.scala
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This is a variant of DataValue specifically for scala 2.11
+ * Due to a bug in the 2.11 compiler (https://github.com/scala/bug/issues/7521), AnyVal classes
+ * do not behave as expected when wrapping a primitive array.
+ * 
+ * For our use-case, this presents a problem, as one of our DataValue types is Array[Byte].
+ * 
+ * To work around this, this implementation will explicitly box/unbox all instances of Array[Byte].
+ */
+package org.apache.daffodil.infoset
+
+import java.lang.{ Boolean => JBoolean, Number => JNumber, Long => JLong, Double => JDouble, String => JString, Float => JFloat, Byte => JByte, Integer => JInt, Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
+import org.apache.daffodil.calendar.DFDLCalendar
+import scala.language.implicitConversions
+import org.apache.daffodil.calendar.DFDLDateTime
+import org.apache.daffodil.calendar.DFDLDate
+import org.apache.daffodil.calendar.DFDLTime
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.processors.UseNilForDefault
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.Maybe.Nope
+import java.io.ObjectOutputStream
+import java.io.ObjectInputStream
+import java.net.URI
+
+/*
+ * These traits are used for the phantom type X. When considering the type of a
+ * DataValue. See the comment on the DataValue class below.
+ */
+trait NonNullable extends Nullable;
+trait Nullable extends tUseNilForDefault;
+trait tUseNilForDefault;
+sealed trait DataValuePrimitiveType
+
+/**
+ * A class to provide basic type safety around infoset and DPath data values.
+ * At runtime, this class goes away, and objects are passed around unboxed as if
+ * we were refering to the underlying objects directly as an AnyRef. Note, however,
+ * that in some circumstances, Scala may still choice to box these objects, resulting
+ * in the same overhead of a normal wrapper class.
+ */
+/*
+ * The type variable X here is a phantom type. That is to say, it is not actually
+ * used to describe the type of anything within DataValue. The goal is to provide us
+ * with more ability to control the inheritense relationship between various DataValue types.
+ * In theory, this would be accomplished by establishing a type hierarchy on the types
+ * used for T. Indeed, if Scala had type-classes as a first-class feature that is likely
+ * the approach we would have taken. However, since most of the types we use for T
+ * are out of our control, we are unable to control what type structure they have.
+ * By carefully selecting X in our type aliases, it is possible for to define types
+ * that can represent any subset of types which we want. It is further possible to
+ * allow for automatic upcasting between these types where appropriate.
+ *
+ */
+final class DataValue[+T <: AnyRef, +X <: AnyRef] private (val v: T) extends AnyVal {
+  @inline def isEmpty = DataValue.NoValue.v eq v
+  @inline def isDefined = !isEmpty
+  @inline def value = v
+  @inline override def toString = if (isEmpty) "NoValue" else "DataValue(" + v.toString + ")"
+
+  @inline def getAnyRef = {
+    if (v.isInstanceOf[BoxedByteArray]) {
+      v.asInstanceOf[BoxedByteArray].v
+    } else {
+      v.asInstanceOf[AnyRef]
+    }
+  }
+  @inline def getBigDecimal = v.asInstanceOf[JBigDecimal]
+  @inline def getCalendar = v.asInstanceOf[DFDLCalendar]
+  @inline def getDate = v.asInstanceOf[DFDLDate]
+  @inline def getTime = v.asInstanceOf[DFDLTime]
+  @inline def getDateTime = v.asInstanceOf[DFDLDateTime]
+  @inline def getByteArray = v.asInstanceOf[BoxedByteArray].v
+  @inline def getBoolean = v.asInstanceOf[JBoolean]
+  @inline def getNumber = v.asInstanceOf[JNumber]
+  @inline def getInt = v.asInstanceOf[JInt]
+  @inline def getLong = v.asInstanceOf[JLong]
+  @inline def getDouble = v.asInstanceOf[JDouble]
+  @inline def getBigInt = v.asInstanceOf[JBigInt]
+  @inline def getString = v.asInstanceOf[JString]
+  @inline def getURI = v.asInstanceOf[URI]
+
+  @inline def getNonNullable = this.asInstanceOf[DataValue[T, X with NonNullable]]
+  @inline def getNullablePrimitive = this.asInstanceOf[DataValue.DataValuePrimitiveNullable]
+
+  @inline def getOptionAnyRef = {
+    if (isEmpty) {
+      None
+    } else {
+      Some(getAnyRef)
+    }
+  }
+
+  @inline def getMaybe[T <: AnyRef]: Maybe[T] = {
+    if (isEmpty) {
+      Nope
+    } else {
+      One(getAnyRef.asInstanceOf[T])
+    }
+  }
+}
+
+object DataValue {
+  /**
+   * All values which are legal for DPath and infoset data values. Note that this incudes
+   *  DINodes, which is legal for DPath, but not infoset data values.
+   *  Also note that at any given time, the infoset may have no value, which is not directly
+   *  representable by this type.
+   */
+  type DataValuePrimitive = DataValue[AnyRef, NonNullable with DataValuePrimitiveType]
+  /**
+   * A (set-theoretic) extension of DataValuePrimitive adjoining a NULL element refered to as NoValue.
+   * Since this just adjoins NoValue, we can think of it as a nullable varient of DataValuePrimitive.
+   * See https://en.wikipedia.org/wiki/Nullable_type
+   */
+  type DataValuePrimitiveNullable = DataValue[AnyRef, Nullable with DataValuePrimitiveType]
+  /**
+   * All values of DataValuePrimitiveNullable, plus a sentinal UseNilForDefault value.
+   * Used only by the default field of ElementRuntimeData.
+   */
+  type DataValuePrimitiveOrUseNilForDefaultOrNull = DataValue[AnyRef, tUseNilForDefault]
+
+  type DataValueEmpty = DataValue[Null, Nullable with DataValuePrimitiveType]
+  type DataValueBigDecimal = DataValue[JBigDecimal, NonNullable with DataValuePrimitiveType]
+  type DataValueCalendar = DataValue[DFDLCalendar, NonNullable with DataValuePrimitiveType]
+  type DataValueDateTime = DataValue[DFDLDateTime, NonNullable with DataValuePrimitiveType]
+  type DataValueDate = DataValue[DFDLDate, NonNullable with DataValuePrimitiveType]
+  type DataValueTime = DataValue[DFDLTime, NonNullable with DataValuePrimitiveType]
+  type DataValueByteArray = DataValue[BoxedByteArray, NonNullable with DataValuePrimitiveType]
+  type DataValueBool = DataValue[JBoolean, NonNullable with DataValuePrimitiveType]
+  type DataValueNumber = DataValue[JNumber, NonNullable with DataValuePrimitiveType]
+  type DataValueLong = DataValue[JLong, NonNullable with DataValuePrimitiveType]
+  type DataValueDouble = DataValue[JDouble, NonNullable with DataValuePrimitiveType]
+  type DataValueBigInt = DataValue[JBigInt, NonNullable with DataValuePrimitiveType]
+  type DataValueString = DataValue[JString, NonNullable with DataValuePrimitiveType]
+  type DataValueURI = DataValue[URI, NonNullable with DataValuePrimitiveType]
+  type DataValueFloat = DataValue[JFloat, NonNullable with DataValuePrimitiveType]
+  type DataValueByte = DataValue[JByte, NonNullable with DataValuePrimitiveType]
+  type DataValueInt = DataValue[JInt, NonNullable with DataValuePrimitiveType]
+  type DataValueShort = DataValue[JShort, NonNullable with DataValuePrimitiveType]
+  type DataValueDINode = DataValue[DINode, NonNullable with DataValuePrimitiveType]
+  type DataValueUseNilForDefault = DataValue[UseNilForDefaultObj, NonNullable]
+
+  import scala.language.implicitConversions
+
+  @inline implicit def toDataValue(v: JBigDecimal): DataValueBigDecimal = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLCalendar): DataValueCalendar = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLDateTime): DataValueDateTime = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLDate): DataValueDate = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLTime): DataValueTime = new DataValue(v)
+  @inline implicit def toDataValue(v: Array[Byte]): DataValueByteArray = new DataValue(new BoxedByteArray(v))
+  @inline implicit def toDataValue(v: JBoolean): DataValueBool = new DataValue(v)
+  @inline implicit def toDataValue(v: JNumber): DataValueNumber = new DataValue(v)
+  @inline implicit def toDataValue(v: JLong): DataValueLong = new DataValue(v)
+  @inline implicit def toDataValue(v: JDouble): DataValueDouble = new DataValue(v)
+  @inline implicit def toDataValue(v: JBigInt): DataValueBigInt = new DataValue(v)
+  @inline implicit def toDataValue(v: JString): DataValueString = new DataValue(v)
+  @inline implicit def toDataValue(v: URI): DataValueURI = new DataValue(v)
+  @inline implicit def toDataValue(v: JFloat): DataValueFloat = new DataValue(v)
+  @inline implicit def toDataValue(v: JByte): DataValueByte = new DataValue(v)
+  @inline implicit def toDataValue(v: JInt): DataValueInt = new DataValue(v)
+  @inline implicit def toDataValue(v: JShort): DataValueShort = new DataValue(v)
+  @inline implicit def toDataValue(v: DINode): DataValueDINode = new DataValue(v)
+
+  @inline implicit def toDataValue(v: Long): DataValueLong = new DataValue(v: JLong)
+  @inline implicit def toDataValue(v: Double): DataValueDouble = new DataValue(v: JDouble)
+  @inline implicit def toDataValue(v: Boolean): DataValueBool = new DataValue(v: JBoolean)
+  @inline implicit def toDataValue(v: Float): DataValueFloat = new DataValue(v: JFloat)
+  @inline implicit def toDataValue(v: Byte): DataValueByte = new DataValue(v: JByte)
+  @inline implicit def toDataValue(v: Int): DataValueInt = new DataValue(v: JInt)
+  @inline implicit def toDataValue(v: Short): DataValueShort = new DataValue(v: JShort)
+
+  @inline def unsafeFromAnyRef(v: AnyRef) = new DataValue(v)
+  @inline def unsafeFromMaybeAnyRef(v: Maybe[AnyRef]) = {
+    if (v.isDefined) {
+      new DataValue(v.get)
+    } else {
+      NoValue
+    }
+  }
+
+  val NoValue: DataValueEmpty = new DataValue(null)
+
+  /**
+   * Used as a sentinal value for Element's defaultValue, when said element
+   *  is nillable and has dfdl:useNilForDefault set to true,
+   */
+  val UseNilForDefault: DataValueUseNilForDefault = new DataValue(new UseNilForDefaultObj)
+
+  final protected class UseNilForDefaultObj {
+    override def toString = "UseNilForDefault"
+  }
+
+  @inline def assertValueIsNotDataValue(v: AnyRef) {
+
+    /*
+   *
+   * In our CompileExpressions classes, we use type variables declared as T <: AnyRef
+   *
+   * Ideally, we would have declared T <: DataValuePrimitive
+   * However, we need to be able to refer to something of the form Maybe[T].
+   * In theory, it should be possible to take a T <: DataValuePrimitive,
+   * and construct a T' <: DataValuePrimitiveNullable, such that T <: T'
+   * In practice, it does not appear to be easy to tell Scala's type system what we want to do,
+   * so we instead punt on this issue and require the caller to translate to/from AnyRef at the boundary.
+   *
+   * In theory, if a caller forgets to do so, and instead passes in a DataValue instead of AnyRef,
+   * the compiler would issue a type error because DataValue is an AnyVal type, and so does not inherit from AnyRef.
+   *
+   * In practice, Scala will "helpfully" box the DataValue for us, which causes all sorts of problems. For instance,
+   * x.asInstanceOf[String] does not work when x is a DataValueString (even though an unboxed DataValueString is literally just a String at runtime).
+   *
+   * To make matters worse, the Scala compiler, does not seem to realize the implications of this autoboxing,
+   * and so believes that is impossible for an AnyRef to ever be an instance of DataValue.
+   * As such, is issues a warning on the naive typecheck since it can "never" fail. We silence this warning,
+   * by first casting to Any.
+   *
+   * Ideally, we could compare against our DataValueAny type alias. However, Scala (correctly) points out,
+   * that type erasure means that DataValueAny contains information that Scala cannot actually verify at runtime.
+   * To silence this warning, we explictly check against the underlying DataValue type.
+   *
+   * The commented out assertion below shows what we are trying to accomplish.
+   *
+   * The actual assertion below is equivalent, but does not result in warnings.
+   *
+   */
+    Assert.invariant(!v.asInstanceOf[Any].isInstanceOf[DataValue[AnyRef, AnyRef]])
+    //  Assert.invariant(!v.isInstanceOf[DataValueAny])
+  }
+}
+
+class BoxedByteArray(val v: Array[Byte]) {
+
+}
\ No newline at end of file
diff --git a/daffodil-runtime1/src/main/scala-2.12/org/apache/daffodil/infoset/DataValue.scala b/daffodil-runtime1/src/main/scala-2.12/org/apache/daffodil/infoset/DataValue.scala
new file mode 100644
index 0000000..c264e3b
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala-2.12/org/apache/daffodil/infoset/DataValue.scala
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.infoset
+
+/*
+ * This version of DataValue is specialized to 2.12 because 2.11 requires having a different implementation.
+ * When supporting future versions of scala, it should be safe to copy this version of DataValue without modification.
+ * When we drop support for 2.11, it should be safe to remove version-specific implementations, and move this file
+ * back to the main src/main/scala tree.
+ */
+import java.lang.{ Boolean => JBoolean, Number => JNumber, Long => JLong, Double => JDouble, String => JString, Float => JFloat, Byte => JByte, Integer => JInt, Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
+import org.apache.daffodil.calendar.DFDLCalendar
+import scala.language.implicitConversions
+import org.apache.daffodil.calendar.DFDLDateTime
+import org.apache.daffodil.calendar.DFDLDate
+import org.apache.daffodil.calendar.DFDLTime
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.processors.UseNilForDefault
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.Maybe.Nope
+import java.io.ObjectOutputStream
+import java.io.ObjectInputStream
+import java.net.URI
+
+/*
+ * These traits are used for the phantom type X. When considering the type of a
+ * DataValue. See the comment on the DataValue class below.
+ */
+trait NonNullable extends Nullable;
+trait Nullable extends tUseNilForDefault;
+trait tUseNilForDefault;
+sealed trait DataValuePrimitiveType
+
+/**
+ * A class to provide basic type safety around infoset and DPath data values.
+ * At runtime, this class goes away, and objects are passed around unboxed as if
+ * we were refering to the underlying objects directly as an AnyRef. Note, however,
+ * that in some circumstances, Scala may still choice to box these objects, resulting
+ * in the same overhead of a normal wrapper class.
+ */
+/*
+ * The type variable X here is a phantom type. That is to say, it is not actually
+ * used to describe the type of anything within DataValue. The goal is to provide us
+ * with more ability to control the inheritense relationship between various DataValue types.
+ * In theory, this would be accomplished by establishing a type hierarchy on the types
+ * used for T. Indeed, if Scala had type-classes as a first-class feature that is likely
+ * the approach we would have taken. However, since most of the types we use for T
+ * are out of our control, we are unable to control what type structure they have.
+ * By carefully selecting X in our type aliases, it is possible for to define types
+ * that can represent any subset of types which we want. It is further possible to
+ * allow for automatic upcasting between these types where appropriate.
+ *
+ */
+final class DataValue[+T <: AnyRef, +X <: AnyRef] private (val v: T) extends AnyVal {
+  @inline def isEmpty = DataValue.NoValue.v eq v
+  @inline def isDefined = !isEmpty
+  @inline def value = v
+  @inline override def toString = if (isEmpty) "NoValue" else "DataValue(" + v.toString + ")"
+
+  @inline def getAnyRef = v.asInstanceOf[AnyRef]
+  @inline def getBigDecimal = v.asInstanceOf[JBigDecimal]
+  @inline def getCalendar = v.asInstanceOf[DFDLCalendar]
+  @inline def getDate = v.asInstanceOf[DFDLDate]
+  @inline def getTime = v.asInstanceOf[DFDLTime]
+  @inline def getDateTime = v.asInstanceOf[DFDLDateTime]
+  @inline def getByteArray = v.asInstanceOf[Array[Byte]]
+  @inline def getBoolean = v.asInstanceOf[JBoolean]
+  @inline def getNumber = v.asInstanceOf[JNumber]
+  @inline def getInt = v.asInstanceOf[JInt]
+  @inline def getLong = v.asInstanceOf[JLong]
+  @inline def getDouble = v.asInstanceOf[JDouble]
+  @inline def getBigInt = v.asInstanceOf[JBigInt]
+  @inline def getString = v.asInstanceOf[JString]
+  @inline def getURI = v.asInstanceOf[URI]
+
+  @inline def getNonNullable = this.asInstanceOf[DataValue[T, X with NonNullable]]
+  @inline def getNullablePrimitive = this.asInstanceOf[DataValue.DataValuePrimitiveNullable]
+
+  @inline def getOptionAnyRef = {
+    if (isEmpty) {
+      None
+    } else {
+      Some(getAnyRef)
+    }
+  }
+
+  @inline def getMaybe[T <: AnyRef]: Maybe[T] = {
+    if (isEmpty) {
+      Nope
+    } else {
+      One(getAnyRef.asInstanceOf[T])
+    }
+  }
+}
+
+object DataValue {
+  /** All values which are legal for DPath and infoset data values. Note that this incudes
+   *  DINodes, which is legal for DPath, but not infoset data values.
+   *  Also note that at any given time, the infoset may have no value, which is not directly 
+   *  representable by this type. 
+   */
+  type DataValuePrimitive = DataValue[AnyRef, NonNullable with DataValuePrimitiveType]
+  /** A (set-theoretic) extension of DataValuePrimitive adjoining a NULL element refered to as NoValue.
+   * Since this just adjoins NoValue, we can think of it as a nullable varient of DataValuePrimitive.
+   * See https://en.wikipedia.org/wiki/Nullable_type
+   */
+  type DataValuePrimitiveNullable = DataValue[AnyRef, Nullable with DataValuePrimitiveType]
+  /** All values of DataValuePrimitiveNullable, plus a sentinal UseNilForDefault value.
+   * Used only by the default field of ElementRuntimeData.
+   */
+  type DataValuePrimitiveOrUseNilForDefaultOrNull = DataValue[AnyRef, tUseNilForDefault]
+
+  type DataValueEmpty = DataValue[Null, Nullable with DataValuePrimitiveType]
+  type DataValueBigDecimal = DataValue[JBigDecimal, NonNullable with DataValuePrimitiveType]
+  type DataValueCalendar = DataValue[DFDLCalendar, NonNullable with DataValuePrimitiveType]
+  type DataValueDateTime = DataValue[DFDLDateTime, NonNullable with DataValuePrimitiveType]
+  type DataValueDate = DataValue[DFDLDate, NonNullable with DataValuePrimitiveType]
+  type DataValueTime = DataValue[DFDLTime, NonNullable with DataValuePrimitiveType]
+  type DataValueByteArray = DataValue[Array[Byte], NonNullable with DataValuePrimitiveType]
+  type DataValueBool = DataValue[JBoolean, NonNullable with DataValuePrimitiveType]
+  type DataValueNumber = DataValue[JNumber, NonNullable with DataValuePrimitiveType]
+  type DataValueLong = DataValue[JLong, NonNullable with DataValuePrimitiveType]
+  type DataValueDouble = DataValue[JDouble, NonNullable with DataValuePrimitiveType]
+  type DataValueBigInt = DataValue[JBigInt, NonNullable with DataValuePrimitiveType]
+  type DataValueString = DataValue[JString, NonNullable with DataValuePrimitiveType]
+  type DataValueURI = DataValue[URI, NonNullable with DataValuePrimitiveType]
+  type DataValueFloat = DataValue[JFloat, NonNullable with DataValuePrimitiveType]
+  type DataValueByte = DataValue[JByte, NonNullable with DataValuePrimitiveType]
+  type DataValueInt = DataValue[JInt, NonNullable with DataValuePrimitiveType]
+  type DataValueShort = DataValue[JShort, NonNullable with DataValuePrimitiveType]
+  type DataValueDINode = DataValue[DINode, NonNullable with DataValuePrimitiveType]
+  type DataValueUseNilForDefault = DataValue[UseNilForDefaultObj, NonNullable]
+
+  import scala.language.implicitConversions
+
+  @inline implicit def toDataValue(v: JBigDecimal): DataValueBigDecimal = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLCalendar): DataValueCalendar = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLDateTime): DataValueDateTime = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLDate): DataValueDate = new DataValue(v)
+  @inline implicit def toDataValue(v: DFDLTime): DataValueTime = new DataValue(v)
+  @inline implicit def toDataValue(v: Array[Byte]): DataValueByteArray = new DataValue(v)
+  @inline implicit def toDataValue(v: JBoolean): DataValueBool = new DataValue(v)
+  @inline implicit def toDataValue(v: JNumber): DataValueNumber = new DataValue(v)
+  @inline implicit def toDataValue(v: JLong): DataValueLong = new DataValue(v)
+  @inline implicit def toDataValue(v: JDouble): DataValueDouble = new DataValue(v)
+  @inline implicit def toDataValue(v: JBigInt): DataValueBigInt = new DataValue(v)
+  @inline implicit def toDataValue(v: JString): DataValueString = new DataValue(v)
+  @inline implicit def toDataValue(v: URI): DataValueURI = new DataValue(v)
+  @inline implicit def toDataValue(v: JFloat): DataValueFloat = new DataValue(v)
+  @inline implicit def toDataValue(v: JByte): DataValueByte = new DataValue(v)
+  @inline implicit def toDataValue(v: JInt): DataValueInt = new DataValue(v)
+  @inline implicit def toDataValue(v: JShort): DataValueShort = new DataValue(v)
+  @inline implicit def toDataValue(v: DINode): DataValueDINode = new DataValue(v)
+
+  @inline implicit def toDataValue(v: Long): DataValueLong = new DataValue(v: JLong)
+  @inline implicit def toDataValue(v: Double): DataValueDouble = new DataValue(v: JDouble)
+  @inline implicit def toDataValue(v: Boolean): DataValueBool = new DataValue(v: JBoolean)
+  @inline implicit def toDataValue(v: Float): DataValueFloat = new DataValue(v: JFloat)
+  @inline implicit def toDataValue(v: Byte): DataValueByte = new DataValue(v: JByte)
+  @inline implicit def toDataValue(v: Int): DataValueInt = new DataValue(v: JInt)
+  @inline implicit def toDataValue(v: Short): DataValueShort = new DataValue(v: JShort)
+
+  @inline def unsafeFromAnyRef(v: AnyRef) = new DataValue(v)
+  @inline def unsafeFromMaybeAnyRef(v: Maybe[AnyRef]) = {
+    if (v.isDefined) {
+      new DataValue(v.get)
+    } else {
+      NoValue
+    }
+  }
+
+  val NoValue: DataValueEmpty = new DataValue(null)
+  
+  /** Used as a sentinal value for Element's defaultValue, when said element
+   *  is nillable and has dfdl:useNilForDefault set to true, 
+   */
+  val UseNilForDefault: DataValueUseNilForDefault = new DataValue(new UseNilForDefaultObj)
+
+  final protected class UseNilForDefaultObj {
+    override def toString = "UseNilForDefault"
+  }
+
+  @inline def assertValueIsNotDataValue(v: AnyRef) {
+
+    /*
+   *
+   * In our CompileExpressions classes, we use type variables declared as T <: AnyRef
+   *
+   * Ideally, we would have declared T <: DataValuePrimitive
+   * However, we need to be able to refer to something of the form Maybe[T].
+   * In theory, it should be possible to take a T <: DataValuePrimitive,
+   * and construct a T' <: DataValuePrimitiveNullable, such that T <: T'
+   * In practice, it does not appear to be easy to tell Scala's type system what we want to do,
+   * so we instead punt on this issue and require the caller to translate to/from AnyRef at the boundary.
+   *
+   * In theory, if a caller forgets to do so, and instead passes in a DataValue instead of AnyRef,
+   * the compiler would issue a type error because DataValue is an AnyVal type, and so does not inherit from AnyRef.
+   *
+   * In practice, Scala will "helpfully" box the DataValue for us, which causes all sorts of problems. For instance,
+   * x.asInstanceOf[String] does not work when x is a DataValueString (even though an unboxed DataValueString is literally just a String at runtime).
+   *
+   * To make matters worse, the Scala compiler, does not seem to realize the implications of this autoboxing,
+   * and so believes that is impossible for an AnyRef to ever be an instance of DataValue.
+   * As such, is issues a warning on the naive typecheck since it can "never" fail. We silence this warning,
+   * by first casting to Any.
+   *
+   * Ideally, we could compare against our DataValueAny type alias. However, Scala (correctly) points out,
+   * that type erasure means that DataValueAny contains information that Scala cannot actually verify at runtime.
+   * To silence this warning, we explictly check against the underlying DataValue type.
+   *
+   * The commented out assertion below shows what we are trying to accomplish.
+   *
+   * The actual assertion below is equivalent, but does not result in warnings.
+   *
+   */
+    Assert.invariant(!v.asInstanceOf[Any].isInstanceOf[DataValue[AnyRef, AnyRef]])
+    //  Assert.invariant(!v.isInstanceOf[DataValueAny])
+  }
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ComparisonOps.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ComparisonOps.scala
index e4e3aea..ea0e563 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ComparisonOps.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ComparisonOps.scala
@@ -22,274 +22,276 @@ import org.apache.daffodil.util.Numbers._
 import org.apache.daffodil.calendar.DFDLDateTime
 import org.apache.daffodil.calendar.DFDLTime
 import org.apache.daffodil.calendar.DFDLDate
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueBool
 
 case object EQ_Compare extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = v1 == v2
     asBoolean(res)
   }
 }
 
 case object EQ_CompareByteArray extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
-    val res = v1.asInstanceOf[Array[Byte]].sameElements(v2.asInstanceOf[Array[Byte]])
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
+    val res = v1.getByteArray.sameElements(v2.getByteArray)
     asBoolean(res)
   }
 }
 
 case object NE_Compare extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = v1 != v2
     asBoolean(res)
   }
 }
 
 case object NE_CompareByteArray extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
-    val res = !v1.asInstanceOf[Array[Byte]].sameElements(v2.asInstanceOf[Array[Byte]])
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
+    val res = !v1.getByteArray.sameElements(v2.getByteArray)
     asBoolean(res)
   }
 }
 
 case object LT_Boolean extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
-    val b1 = asBoolean(v1)
-    val b2 = asBoolean(v2)
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
+    val b1 = asBoolean(v1.getAnyRef)
+    val b2 = asBoolean(v2.getAnyRef)
 
     val res = (!b1 && b2)
     asBoolean(res)
   }
 }
 case object GT_Boolean extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
-    val b1 = asBoolean(v1)
-    val b2 = asBoolean(v2)
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
+    val b1 = asBoolean(v1.getAnyRef)
+    val b2 = asBoolean(v2.getAnyRef)
 
     val res = (b1 && !b2)
     asBoolean(res)
   }
 }
 case object LE_Boolean extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { !GT_Boolean.operate(v1, v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { !GT_Boolean.operate(v1, v2).getBoolean }
 }
 case object GE_Boolean extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { !LT_Boolean.operate(v1, v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { !LT_Boolean.operate(v1, v2).getBoolean }
 }
 
 case object LT_Date extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDate] < v2.asInstanceOf[DFDLDate] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDate < v2.getDate }
 }
 case object GT_Date extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDate] > v2.asInstanceOf[DFDLDate] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDate > v2.getDate }
 }
 case object LE_Date extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDate] <= v2.asInstanceOf[DFDLDate] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDate <= v2.getDate }
 }
 case object GE_Date extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDate] >= v2.asInstanceOf[DFDLDate] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDate >= v2.getDate }
 }
 case object LT_Time extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLTime] < v2.asInstanceOf[DFDLTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getTime < v2.getTime }
 }
 case object GT_Time extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLTime] > v2.asInstanceOf[DFDLTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getTime > v2.getTime }
 }
 case object LE_Time extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLTime] <= v2.asInstanceOf[DFDLTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getTime <= v2.getTime }
 }
 case object GE_Time extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLTime] >= v2.asInstanceOf[DFDLTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getTime >= v2.getTime }
 }
 case object LT_DateTime extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDateTime] < v2.asInstanceOf[DFDLDateTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDateTime < v2.getDateTime }
 }
 case object GT_DateTime extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDateTime] > v2.asInstanceOf[DFDLDateTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDateTime > v2.getDateTime }
 }
 case object LE_DateTime extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDateTime] <= v2.asInstanceOf[DFDLDateTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDateTime <= v2.getDateTime }
 }
 case object GE_DateTime extends CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { v1.asInstanceOf[DFDLDateTime] >= v2.asInstanceOf[DFDLDateTime] }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { v1.getDateTime >= v2.getDateTime }
 }
 
 case object LT_String extends StringCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = compare(v1, v2) < 0
     res
   }
 }
 case object GT_String extends StringCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = compare(v1, v2) > 0
     res
   }
 }
 case object LE_String extends StringCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = compare(v1, v2) <= 0
     res
   }
 }
 case object GE_String extends StringCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = {
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = {
     val res = compare(v1, v2) >= 0
     res
   }
 }
 case object LT_Decimal extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigDecimal(v1).compareTo(asBigDecimal(v2)) == -1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigDecimal(v1.getAnyRef).compareTo(asBigDecimal(v2.getAnyRef)) == -1 }
 }
 case object GT_Decimal extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigDecimal(v1).compareTo(asBigDecimal(v2)) == 1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigDecimal(v1.getAnyRef).compareTo(asBigDecimal(v2.getAnyRef)) == 1 }
 }
 case object LE_Decimal extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigDecimal(v1).compareTo(asBigDecimal(v2)) <= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigDecimal(v1.getAnyRef).compareTo(asBigDecimal(v2.getAnyRef)) <= 0 }
 }
 case object GE_Decimal extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigDecimal(v1).compareTo(asBigDecimal(v2)) >= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigDecimal(v1.getAnyRef).compareTo(asBigDecimal(v2.getAnyRef)) >= 0 }
 }
 case object LT_Integer extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == -1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == -1 }
 }
 case object GT_Integer extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == 1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == 1 }
 }
 case object LE_Integer extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) <= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) <= 0 }
 }
 case object GE_Integer extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) >= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) >= 0 }
 }
 case object LT_NonNegativeInteger extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == -1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == -1 }
 }
 case object GT_NonNegativeInteger extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == 1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == 1 }
 }
 case object LE_NonNegativeInteger extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) <= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) <= 0 }
 }
 case object GE_NonNegativeInteger extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) >= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) >= 0 }
 }
 case object LT_UnsignedLong extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == -1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == -1 }
 }
 case object GT_UnsignedLong extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) == 1 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) == 1 }
 }
 case object LE_UnsignedLong extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) <= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) <= 0 }
 }
 case object GE_UnsignedLong extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asBigInt(v1).compareTo(asBigInt(v2)) >= 0 }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asBigInt(v1.getAnyRef).compareTo(asBigInt(v2.getAnyRef)) >= 0 }
 }
 case object LT_Long extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) < asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) < asLong(v2.getAnyRef) }
 }
 case object GT_Long extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) > asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) > asLong(v2.getAnyRef) }
 }
 case object LE_Long extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) <= asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) <= asLong(v2.getAnyRef) }
 }
 case object GE_Long extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) >= asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) >= asLong(v2.getAnyRef) }
 }
 case object LT_UnsignedInt extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) < asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) < asLong(v2.getAnyRef) }
 }
 case object GT_UnsignedInt extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) > asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) > asLong(v2.getAnyRef) }
 }
 case object LE_UnsignedInt extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) <= asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) <= asLong(v2.getAnyRef) }
 }
 case object GE_UnsignedInt extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asLong(v1) >= asLong(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asLong(v1.getAnyRef) >= asLong(v2.getAnyRef) }
 }
 case object LT_Int extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) < asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) < asInt(v2.getAnyRef) }
 }
 case object GT_Int extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) > asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) > asInt(v2.getAnyRef) }
 }
 case object LE_Int extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) <= asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) <= asInt(v2.getAnyRef) }
 }
 case object GE_Int extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) >= asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) >= asInt(v2.getAnyRef) }
 }
 case object LT_UnsignedShort extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) < asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) < asInt(v2.getAnyRef) }
 }
 case object GT_UnsignedShort extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) > asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) > asInt(v2.getAnyRef) }
 }
 case object LE_UnsignedShort extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) <= asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) <= asInt(v2.getAnyRef) }
 }
 case object GE_UnsignedShort extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asInt(v1) >= asInt(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asInt(v1.getAnyRef) >= asInt(v2.getAnyRef) }
 }
 case object LT_Short extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) < asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) < asShort(v2.getAnyRef) }
 }
 case object GT_Short extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) > asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) > asShort(v2.getAnyRef) }
 }
 case object LE_Short extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) <= asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) <= asShort(v2.getAnyRef) }
 }
 case object GE_Short extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) >= asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) >= asShort(v2.getAnyRef) }
 }
 case object LT_UnsignedByte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) < asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) < asShort(v2.getAnyRef) }
 }
 case object GT_UnsignedByte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) > asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) > asShort(v2.getAnyRef) }
 }
 case object LE_UnsignedByte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) <= asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) <= asShort(v2.getAnyRef) }
 }
 case object GE_UnsignedByte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asShort(v1) >= asShort(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asShort(v1.getAnyRef) >= asShort(v2.getAnyRef) }
 }
 case object LT_Byte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asByte(v1) < asByte(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asByte(v1.getAnyRef) < asByte(v2.getAnyRef) }
 }
 case object GT_Byte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asByte(v1) > asByte(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asByte(v1.getAnyRef) > asByte(v2.getAnyRef) }
 }
 case object LE_Byte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asByte(v1) <= asByte(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asByte(v1.getAnyRef) <= asByte(v2.getAnyRef) }
 }
 case object GE_Byte extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asByte(v1) >= asByte(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asByte(v1.getAnyRef) >= asByte(v2.getAnyRef) }
 }
 case object LT_Float extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asFloat(v1) < asFloat(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asFloat(v1.getAnyRef) < asFloat(v2.getAnyRef) }
 }
 case object GT_Float extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asFloat(v1) > asFloat(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asFloat(v1.getAnyRef) > asFloat(v2.getAnyRef) }
 }
 case object LE_Float extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asFloat(v1) <= asFloat(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asFloat(v1.getAnyRef) <= asFloat(v2.getAnyRef) }
 }
 case object GE_Float extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asFloat(v1) >= asFloat(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asFloat(v1.getAnyRef) >= asFloat(v2.getAnyRef) }
 }
 case object LT_Double extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asDouble(v1) < asDouble(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asDouble(v1.getAnyRef) < asDouble(v2.getAnyRef) }
 }
 case object GT_Double extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asDouble(v1) > asDouble(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asDouble(v1.getAnyRef) > asDouble(v2.getAnyRef) }
 }
 case object LE_Double extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asDouble(v1) <= asDouble(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asDouble(v1.getAnyRef) <= asDouble(v2.getAnyRef) }
 }
 case object GE_Double extends NumberCompareOp {
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean = { asDouble(v1) >= asDouble(v2) }
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool = { asDouble(v1.getAnyRef) >= asDouble(v2.getAnyRef) }
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps.scala
index 52c5376..a64a784 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps.scala
@@ -17,71 +17,101 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.util.Numbers._
-import org.apache.daffodil.calendar.DFDLDateTime
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+
 import org.apache.daffodil.calendar.DFDLDate
-import java.lang.{ Byte => JByte, Short => JShort, Integer => JInt, Long => JLong, Float => JFloat, Double => JDouble, Boolean => JBoolean }
-import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
+import org.apache.daffodil.calendar.DFDLDateTime
+import org.apache.daffodil.infoset.DataValue.DataValueBigDecimal
+import org.apache.daffodil.infoset.DataValue.DataValueBigInt
+import org.apache.daffodil.infoset.DataValue.DataValueBool
+import org.apache.daffodil.infoset.DataValue.DataValueByte
+import org.apache.daffodil.infoset.DataValue.DataValueDate
+import org.apache.daffodil.infoset.DataValue.DataValueDateTime
+import org.apache.daffodil.infoset.DataValue.DataValueDouble
+import org.apache.daffodil.infoset.DataValue.DataValueFloat
+import org.apache.daffodil.infoset.DataValue.DataValueInt
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueShort
+import org.apache.daffodil.infoset.DataValue.DataValueString
+import org.apache.daffodil.infoset.DataValue.DataValueTime
+import org.apache.daffodil.util.Numbers.asBigDecimal
+import org.apache.daffodil.util.Numbers.asBigInt
+import org.apache.daffodil.util.Numbers.asBoolean
+import org.apache.daffodil.util.Numbers.asByte
+import org.apache.daffodil.util.Numbers.asDouble
+import org.apache.daffodil.util.Numbers.asFloat
+import org.apache.daffodil.util.Numbers.asInt
+import org.apache.daffodil.util.Numbers.asLong
+import org.apache.daffodil.util.Numbers.asShort
 import org.apache.daffodil.xml.XMLUtils
 
 case object BooleanToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = JLong.valueOf(if (asBoolean(a) == true) 1L else 0L)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = JLong.valueOf(if (asBoolean(a.getAnyRef) == true) 1L else 0L)
 }
 
 case object BooleanToString extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = if (asBoolean(a) == true) "true" else "false"
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueString = if (asBoolean(a.getAnyRef) == true) "true" else "false"
 }
 
 case object DateTimeToDate extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDate = {
+    a.getAnyRef match {
       case dt: DFDLDateTime => dt.toDate
       case _ => throw new NumberFormatException("xs:dateTime expected but an invalid type was received.")
     }
   }
 }
 case object DateTimeToTime extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueTime = {
+    a.getAnyRef match {
       case dt: DFDLDateTime => dt.toTime
       case _ => throw new NumberFormatException("xs:dateTime expected but an invalid type was received.")
     }
   }
 }
 case object DateToDateTime extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDateTime = {
+    a.getAnyRef match {
       case d: DFDLDate => d.toDateTime
       case _ => throw new NumberFormatException("xs:date expected but an invalid type was received.")
     }
   }
 }
 case object DecimalToInteger extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asBigDecimal(a).toBigInteger()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = asBigDecimal(a.getAnyRef).toBigInteger()
 }
 case object DecimalToLong extends Converter {
   val MAX_VALUE = JBigDecimal.valueOf(Long.MaxValue)
   val MIN_VALUE = JBigDecimal.valueOf(Long.MinValue)
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigDecimal(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val res = asBigDecimal(a.getAnyRef)
     if (res.compareTo(MIN_VALUE) == -1 || res.compareTo(MAX_VALUE) == 1) throw new NumberFormatException("Value %s out of range for Long type.".format(res))
     asLong(res)
   }
 }
 case object DecimalToDouble extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asDouble(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble = asDouble(a.getAnyRef)
 }
 case object DecimalToNonNegativeInteger extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigDecimal(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = asBigDecimal(a.getAnyRef)
     if (res.compareTo(JBigDecimal.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to a non-negative integer.".format(res))
     res.toBigInteger()
   }
 }
 case object DecimalToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigDecimal(a).toBigInteger()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = asBigDecimal(a.getAnyRef).toBigInteger()
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to a non-negative integer.".format(res))
 
     if (res.compareTo(NodeInfo.UnsignedLong.Max) == 1) throw new NumberFormatException("Value %s out of range for UnsignedLong type.".format(res))
@@ -89,8 +119,8 @@ case object DecimalToUnsignedLong extends Converter {
   }
 }
 case object DecimalToBoolean extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val d = asBigDecimal(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val d = asBigDecimal(a.getAnyRef)
     val comp = d.compareTo(JBigDecimal.ZERO)
     val b =
       if (comp == 0) false
@@ -99,34 +129,34 @@ case object DecimalToBoolean extends Converter {
   }
 }
 case object DoubleToDecimal extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = JBigDecimal.valueOf(asDouble(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal = JBigDecimal.valueOf(asDouble(a.getAnyRef))
 }
 case object DoubleToFloat extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val f = asFloat(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueFloat = {
+    val f = asFloat(a.getAnyRef)
     f
   }
 }
 case object DoubleToLong extends Converter {
   val MAX_VALUE = JBigDecimal.valueOf(Long.MaxValue)
   val MIN_VALUE = JBigDecimal.valueOf(Long.MinValue)
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigDecimal(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val res = asBigDecimal(a.getAnyRef)
     if (res.compareTo(MIN_VALUE) == -1 || res.compareTo(MAX_VALUE) == 1) throw new NumberFormatException("Value %s out of range for Long type.".format(res))
-    asLong(a)
+    asLong(a.getAnyRef)
   }
 }
 case object DoubleToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigInt(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = asBigInt(a.getAnyRef)
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned long.".format(res))
     if (res.compareTo(NodeInfo.UnsignedLong.Max) == 1) throw new NumberFormatException("Value %s out of range for UnsignedLong type.".format(res))
     else res
   }
 }
 case object DoubleToBoolean extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val d = asDouble(a).doubleValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val d = asDouble(a.getAnyRef).doubleValue()
     val b =
       if (d == 0.0) false
       else if (d.isNaN()) false
@@ -135,75 +165,75 @@ case object DoubleToBoolean extends Converter {
   }
 }
 case object FloatToDouble extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asDouble(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble = asDouble(a.getAnyRef)
 }
 case object IntegerToDecimal extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = new JBigDecimal(asBigInt(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal = new JBigDecimal(asBigInt(a.getAnyRef))
 }
 case object IntegerToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigInt(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = asBigInt(a.getAnyRef)
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned long.".format(res))
     if (res.compareTo(NodeInfo.UnsignedLong.Max) == 1) throw new NumberFormatException("Value %s out of range for UnsignedLong type.".format(res))
     else res
   }
 }
 case object LongToBoolean extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asBoolean(if (asLong(a) == 0) false else true)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = asBoolean(if (asLong(a.getAnyRef) == 0) false else true)
 }
 case object LongToByte extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val l = asLong(a).longValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueByte = {
+    val l = a.getLong
     if (l > Byte.MaxValue || l < Byte.MinValue) throw new NumberFormatException("Value %s out of range for Byte type.".format(l))
-    asByte(a)
+    asByte(l)
   }
 }
 case object LongToDecimal extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = JBigDecimal.valueOf(asLong(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal = JBigDecimal.valueOf(asLong(a.getAnyRef))
 }
 case object LongToDouble extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asDouble(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble = asDouble(a.getAnyRef)
 }
 case object LongToFloat extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asFloat(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueFloat = asFloat(a.getAnyRef)
 }
 case object LongToInt extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val l = asLong(a).longValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt = {
+    val l = asLong(a.getAnyRef).longValue()
     if (l > Int.MaxValue || l < Int.MinValue) throw new NumberFormatException("Value %s out of range for Int type.".format(l))
-    asInt(a)
+    asInt(a.getAnyRef)
   }
 }
 
 case object LongToInteger extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = JBigInt.valueOf(asLong(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = JBigInt.valueOf(asLong(a.getAnyRef))
 }
 
 case object LongToShort extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val l = asLong(a).longValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueShort = {
+    val l = asLong(a.getAnyRef).longValue()
     if (l > Short.MaxValue || l < Short.MinValue) throw new NumberFormatException("Value %s out of range for Short type.".format(l))
-    asShort(a)
+    asShort(a.getAnyRef)
   }
 }
 
 case object LongToArrayIndex extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val res = asLong(a.getAnyRef)
     res
   }
 }
 case object LongToUnsignedByte extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asLong(a).longValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueShort = {
+    val res = asLong(a.getAnyRef).longValue()
     if (res < 0) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned byte.".format(res))
     if (res > 255) throw new NumberFormatException("Value %s out of range for unsigned byte.".format(res))
-    asShort(a)
+    asShort(a.getAnyRef)
   }
 }
 case object LongToUnsignedInt extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val r = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val r = asLong(a.getAnyRef)
     val res = r.longValue()
     if (res < 0) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned int.".format(res))
     if (res > 0xFFFFFFFFL) throw new NumberFormatException("Value %s out of range for unsigned int.".format(res))
@@ -211,37 +241,37 @@ case object LongToUnsignedInt extends Converter {
   }
 }
 case object LongToUnsignedShort extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asLong(a).longValue()
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt = {
+    val res = asLong(a.getAnyRef).longValue()
     if (res < 0) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned short.".format(res))
     if (res > 65535) throw new NumberFormatException("Value %s out of range for unsigned short.".format(res))
-    asInt(a)
+    asInt(a.getAnyRef)
   }
 }
 
 case object LongToNonNegativeInteger extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = JBigInt.valueOf(asLong(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = JBigInt.valueOf(asLong(a.getAnyRef))
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to a non-negative integer.".format(res))
     res
   }
 }
 
 case object LongToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = JBigInt.valueOf(asLong(a))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = JBigInt.valueOf(asLong(a.getAnyRef))
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to a non-negative integer.".format(res))
     else res
   }
 }
 
 case object NumericToDouble extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asDouble(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble = asDouble(a.getAnyRef)
 }
 
 case object StringToBoolean extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val str = a.asInstanceOf[String]
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val str = a.getString
     val res =
       if (str == "true" || str == "1") true
       else if (str == "false" || str == "0") false
@@ -250,24 +280,24 @@ case object StringToBoolean extends Converter {
   }
 }
 case object StringToDecimal extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = new JBigDecimal(a.asInstanceOf[String])
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal = new JBigDecimal(a.getString)
 }
 case object StringToDouble extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val str = a.asInstanceOf[String]
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble = {
+    val str = a.getString
     val d =
       if (str == XMLUtils.PositiveInfinityString) JDouble.POSITIVE_INFINITY
       else if (str == XMLUtils.NegativeInfinityString) JDouble.NEGATIVE_INFINITY
       else if (str == XMLUtils.NaNString) JDouble.NaN
       else str.toDouble
-    asAnyRef(d)
+    d
   }
 }
 case object StringToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
     val res =
       try {
-        asAnyRef(a.asInstanceOf[String].toLong)
+        a.getString.toLong
       } catch {
         case nfe: NumberFormatException => {
           val e = new NumberFormatException("Cannot convert to type long: " + nfe.getMessage())
@@ -278,8 +308,8 @@ case object StringToLong extends Converter {
   }
 }
 case object StringToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = new JBigInt(a.asInstanceOf[String])
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res = new JBigInt(a.getString)
     if (res.compareTo(JBigInt.ZERO) == -1) throw new NumberFormatException("Negative value %s cannot be converted to an unsigned long.".format(res))
     if (res.compareTo(NodeInfo.UnsignedLong.Max) == 1) throw new NumberFormatException("Value %s out of range for UnsignedLong type.".format(res))
     else res
@@ -308,8 +338,8 @@ case object StringToUnsignedLong extends Converter {
  * In all other cases, fn:boolean raises a type error [err:FORG0006].
  */
 case object FNToBoolean extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val res = a.getAnyRef match {
       case b: JBoolean => b.booleanValue()
       case s: String => if (s.length == 0) false else true
       case d: JDouble => if (d.isNaN() || d == 0) false else true
@@ -327,6 +357,6 @@ case object FNToBoolean extends Converter {
       //case s: Sequence if s(0) == Node => true
       case _ => throw new NumberFormatException("Invalid argument type.")
     }
-    asAnyRef(res)
+    res
   }
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps2.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps2.scala
index c98c85e..2a76745 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps2.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps2.scala
@@ -17,16 +17,17 @@
 
 package org.apache.daffodil.dpath
 
-import com.ibm.icu.text.SimpleDateFormat
-import com.ibm.icu.util.Calendar
-
-import org.apache.daffodil.calendar.DFDLCalendar
 import org.apache.daffodil.calendar.DFDLDate
 import org.apache.daffodil.calendar.DFDLDateConversion
 import org.apache.daffodil.calendar.DFDLDateTime
 import org.apache.daffodil.calendar.DFDLDateTimeConversion
 import org.apache.daffodil.calendar.DFDLTime
 import org.apache.daffodil.calendar.DFDLTimeConversion
+import org.apache.daffodil.infoset.DataValue.DataValueByteArray
+import org.apache.daffodil.infoset.DataValue.DataValueDate
+import org.apache.daffodil.infoset.DataValue.DataValueDateTime
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueTime
 
 case object AnyAtomicToString extends ToString {
   val name = "AnyAtomicToString"
@@ -35,8 +36,8 @@ case object AnyAtomicToString extends ToString {
 case object StringToDate extends Converter {
   val name = "StringToDate"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDate = {
+    val result = a.getAnyRef match {
       case cal: DFDLDateTime => cal.toDate
       case cal: DFDLDate => cal
       case str: String => DFDLDateConversion.fromXMLString(str)
@@ -49,8 +50,8 @@ case object StringToDate extends Converter {
 case object StringToDateTime extends Converter {
   val name = "StringToDateTime"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDateTime = {
+    val result = a.getAnyRef match {
       case cal: DFDLDateTime => cal
       case cal: DFDLDate => cal.toDateTime
       case str: String => DFDLDateTimeConversion.fromXMLString(str)
@@ -63,8 +64,8 @@ case object StringToDateTime extends Converter {
 case object StringToTime extends Converter {
   val name = "StringToTime"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueTime = {
+    val result = a.getAnyRef match {
       case cal: DFDLDateTime => cal.toTime
       case cal: DFDLTime => cal
       case str: String => DFDLTimeConversion.fromXMLString(str)
@@ -77,8 +78,8 @@ case object StringToTime extends Converter {
 case object StringToHexBinary extends Converter with HexBinaryKind {
   val name = "StringToHexBinary"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueByteArray = {
+    val result = a.getAnyRef match {
       case s: String => hexStringToByteArray(s)
       case hb: Array[Byte] => hb
       case x => throw new NumberFormatException("%s cannot be cast to dfdl:hexBinary\ndfdl:hexBinary received an unrecognized type! Must be String or HexBinary.".format(x.toString))
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps3.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps3.scala
index dcbc2a7..a680334 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps3.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/ConverterOps3.scala
@@ -17,24 +17,30 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.util.Numbers._
-import org.apache.daffodil.util.Misc
 import java.math.{ BigInteger => JBigInt }
 
+import org.apache.daffodil.infoset.DataValue.DataValueBigInt
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueString
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.util.Numbers.asBigInt
+import org.apache.daffodil.util.Numbers.asLong
+
 case object NumericToString extends ToString
 case object DateTimeToString extends ToString
 case object HexBinaryToString extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val bytes = a.asInstanceOf[Array[Byte]]
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueString = {
+    val bytes = a.getByteArray
     val hex = Misc.bytes2Hex(bytes)
     hex
   }
 }
 case object HexStringToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
     val res =
       try {
-        val str = a.asInstanceOf[String]
+        val str = a.getString
         java.lang.Long.parseLong(str, 16)
       } catch {
         case nfe: NumberFormatException => {
@@ -42,15 +48,15 @@ case object HexStringToLong extends Converter {
           throw e
         }
       }
-    asAnyRef(res)
+    res
   }
 }
 case object HexStringToUnsignedLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res =
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt = {
+    val res: DataValueBigInt =
       try {
-        val str = a.asInstanceOf[String]
-        BigInt(str, 16)
+        val str = a.getString
+        new JBigInt(str, 16)
       } catch {
         case nfe: NumberFormatException => {
           val e = new NumberFormatException("Cannot convert to type unsignedLong: " + nfe.getMessage())
@@ -63,44 +69,43 @@ case object HexStringToUnsignedLong extends Converter {
 case object BigIntToLong extends Converter {
   val MAX_VALUE = JBigInt.valueOf(Long.MaxValue)
   val MIN_VALUE = JBigInt.valueOf(Long.MinValue)
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigInt(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val res = asBigInt(a.getAnyRef)
     if (res.compareTo(MIN_VALUE) == -1 || res.compareTo(MAX_VALUE) == 1) throw new NumberFormatException("Value %s out of range for Long type.".format(res))
     asLong(res)
   }
 }
 case object IntToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = asLong(a.getAnyRef)
 }
 case object UnsignedLongToLong extends Converter {
   val MAX_VALUE = JBigInt.valueOf(Long.MaxValue)
   val MIN_VALUE = JBigInt.valueOf(Long.MinValue)
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val res = asBigInt(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    val res = asBigInt(a.getAnyRef)
     if (res.compareTo(MIN_VALUE) == -1 || res.compareTo(MAX_VALUE) == 1) throw new NumberFormatException("Value %s out of range for Long type.".format(res))
     asLong(res)
   }
 }
 case object UnsignedIntToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    // Assert.invariant(a.isInstanceOf[Long])
-    asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    asLong(a.getAnyRef)
   }
 }
 case object ArrayIndexToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = {
+    asLong(a.getAnyRef)
   }
 }
 case object ShortToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = asLong(a.getAnyRef)
 }
 case object UnsignedShortToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = asLong(a.getAnyRef)
 }
 case object ByteToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = asLong(a.getAnyRef)
 }
 case object UnsignedByteToLong extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asLong(a)
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong = asLong(a.getAnyRef)
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLConstructors.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLConstructors.scala
index fd70dbd..21e8caa 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLConstructors.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLConstructors.scala
@@ -17,9 +17,21 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.util.Numbers._
-import java.lang.{ Byte => JByte, Short => JShort, Integer => JInt, Long => JLong }
-import java.math.{ BigInteger => JBigInt, BigDecimal => JBigDecimal }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+
+import org.apache.daffodil.infoset.DataValue.DataValueBigInt
+import org.apache.daffodil.infoset.DataValue.DataValueByte
+import org.apache.daffodil.infoset.DataValue.DataValueByteArray
+import org.apache.daffodil.infoset.DataValue.DataValueInt
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueShort
+import org.apache.daffodil.util.Numbers.asBigInt
 
 abstract class DFDLConstructorFunction(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
@@ -30,10 +42,10 @@ abstract class DFDLConstructorFunction(recipe: CompiledDPath, argType: NodeInfo.
   lazy val nfeMsg = "%s cannot be cast to dfdl:" + constructorName + "\ndfdl:" + constructorName + " received an unrecognized type! Must be String, Byte, Short, Integer, Long or a subtype thereof."
   lazy val hexMsg = "dfdl:" + constructorName + " received string violates maximum hex digits.  Received %s expected a max of " + maxHexDigits
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValuePrimitive
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val long = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    val long:DataValueLong = a.getAnyRef match {
       case _: JByte | _: JShort | _: JInt => IntToLong.computeValue(a, dstate)
       case l: JLong => l
       case s: String if s.startsWith("x") => {
@@ -47,13 +59,13 @@ abstract class DFDLConstructorFunction(recipe: CompiledDPath, argType: NodeInfo.
       case bi: JBigInt => BigIntToLong.computeValue(bi, dstate)
       case bd: JBigDecimal if (bd.remainder(JBigDecimal.ONE) == JBigDecimal.ZERO) => BigIntToLong.computeValue(bd.toBigInteger(), dstate)
       case hb: Array[Byte] => {
-        val str = "0x" + HexBinaryToString.computeValue(hb, dstate)
+        val str = "0x" + HexBinaryToString.computeValue(hb, dstate).getString
         throw new NumberFormatException(nfeMsg.format(str))
       }
       case x =>
         throw new NumberFormatException(nfeMsg.format(x))
     }
-    convert(asLong(long), dstate)
+    convert(long, dstate)
   }
 }
 
@@ -97,8 +109,8 @@ case class DFDLHexBinary(recipe: CompiledDPath, argType: NodeInfo.Kind)
    * is also D0 dfdl:hexBinary(xs:short(208)) is 00D0
    *
    */
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val arr = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueByteArray = {
+    val arr = a.getAnyRef match {
       case s: String => {
         // Literal number
         reduce(s)
@@ -135,7 +147,7 @@ case class DFDLByte(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "byte"
   val maxHexDigits = 2
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToByte.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueByte = LongToByte.computeValue(longValue, dstate)
 }
 
 case class DFDLUnsignedByte(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -143,7 +155,7 @@ case class DFDLUnsignedByte(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "unsignedByte"
   val maxHexDigits = 2
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToUnsignedByte.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueShort = LongToUnsignedByte.computeValue(longValue, dstate)
 }
 
 case class DFDLShort(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -151,7 +163,7 @@ case class DFDLShort(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "short"
   val maxHexDigits = 4
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToShort.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueShort = LongToShort.computeValue(longValue, dstate)
 }
 
 case class DFDLUnsignedShort(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -159,7 +171,7 @@ case class DFDLUnsignedShort(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "unsignedShort"
   val maxHexDigits = 4
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToUnsignedShort.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueInt = LongToUnsignedShort.computeValue(longValue, dstate)
 }
 
 case class DFDLInt(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -167,7 +179,7 @@ case class DFDLInt(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "int"
   val maxHexDigits = 8
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToInt.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueInt = LongToInt.computeValue(longValue, dstate)
 }
 
 case class DFDLUnsignedInt(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -175,7 +187,7 @@ case class DFDLUnsignedInt(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "unsignedInt"
   val maxHexDigits = 8
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = LongToUnsignedInt.computeValue(longValue, dstate)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueLong = LongToUnsignedInt.computeValue(longValue, dstate)
 }
 
 case class DFDLLong(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -183,7 +195,7 @@ case class DFDLLong(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "long"
   val maxHexDigits = 16
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = longValue
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueLong = longValue
 }
 
 case class DFDLUnsignedLong(recipe: CompiledDPath, argType: NodeInfo.Kind)
@@ -191,10 +203,10 @@ case class DFDLUnsignedLong(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val constructorName = "unsignedLong"
   val maxHexDigits = 16
 
-  protected def convert(longValue: JLong, dstate: DState): AnyRef = asBigInt(longValue)
+  protected def convert(longValue: DataValueLong, dstate: DState): DataValueBigInt = asBigInt(longValue.getLong)
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val ulong = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    val ulong: DataValuePrimitive = a.getAnyRef match {
       case _: JByte | _: JShort | _: JInt => IntegerToUnsignedLong.computeValue(a, dstate)
       case s: String if s.startsWith("x") => {
         val hexStr = s.substring(1)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions.scala
index 11133cc..0ed5484 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions.scala
@@ -17,12 +17,13 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.calendar.DFDLCalendar
 import org.apache.daffodil.calendar.DFDLCalendarConversion
 import org.apache.daffodil.cookers.EntityReplacer
-import org.apache.daffodil.dsom._
-import org.apache.daffodil.exceptions._
-import org.apache.daffodil.util.Numbers._
+import org.apache.daffodil.dsom.SchemaDefinitionError
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DataValue.DataValueBool
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueString
 
 case class DFDLCheckConstraints(recipe: CompiledDPath) extends RecipeOpWithSubRecipes(recipe) {
   override def run(dstate: DState) {
@@ -38,14 +39,14 @@ case class DFDLCheckConstraints(recipe: CompiledDPath) extends RecipeOpWithSubRe
 }
 
 case class DFDLDecodeDFDLEntities(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) = {
-    val dfdlString = EntityReplacer { _.replaceAll(str.asInstanceOf[String], None) }
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueString = {
+    val dfdlString = EntityReplacer { _.replaceAll(str.getString, None) }
     dfdlString
   }
 }
 
 case class DFDLEncodeDFDLEntities(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) = constructLiteral(str.asInstanceOf[String])
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueString = constructLiteral(str.getString)
 
   def constructLiteral(s: String) = {
     val sb = new StringBuilder
@@ -97,8 +98,8 @@ case class DFDLEncodeDFDLEntities(recipe: CompiledDPath, argType: NodeInfo.Kind)
 }
 
 case class DFDLContainsDFDLEntities(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) =
-    EntityReplacer { x => asAnyRef(x.hasDfdlEntity(str.asInstanceOf[String])) }
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueBool =
+    EntityReplacer { x => x.hasDfdlEntity(str.getString) }
 }
 
 /**
@@ -114,8 +115,8 @@ case class DFDLContainsDFDLEntities(recipe: CompiledDPath, argType: NodeInfo.Kin
 case class DFDLTimeZoneFromDFDLCalendar(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
 
-  override def computeValue(value: AnyRef, dstate: DState) = {
-    val dfdlcal = value.asInstanceOf[DFDLCalendar]
+  override def computeValue(value: DataValuePrimitive, dstate: DState):DataValueString = {
+    val dfdlcal = value.getCalendar
     DFDLCalendarConversion.timeZonePartToXMLString(dfdlcal)
   }
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions2.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions2.scala
index d6df086..6c065af 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions2.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLFunctions2.scala
@@ -17,11 +17,15 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.schema.annotation.props.gen.LengthUnits
-import org.apache.daffodil.infoset.LengthState
 import java.lang.{ Long => JLong }
+
+import org.apache.daffodil.infoset.DIElement
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.LengthState
+import org.apache.daffodil.schema.annotation.props.gen.LengthUnits
+
 import passera.unsigned.ULong
-import org.apache.daffodil.infoset._
 
 sealed abstract class DFDLLengthFunctionBase(kind: String, recipes: List[CompiledDPath]) extends FNTwoArgsNodeAndValue(recipes) {
 
@@ -55,14 +59,14 @@ sealed abstract class DFDLLengthFunctionBase(kind: String, recipes: List[Compile
     len
   }
 
-  override def computeValue(anyNode: AnyRef, str: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(anyNode: DataValuePrimitive, str: DataValuePrimitive, dstate: DState): DataValueLong = {
 
-    val elt = anyNode match {
+    val elt = anyNode.getAnyRef match {
       case e: DIElement => e
       case _ => throw new IllegalArgumentException("dfdl:%sLength's first argument must be an Infoset Element. Argument was: %s".format(kind, anyNode))
     }
 
-    val units = str match {
+    val units = str.getAnyRef match {
       case s: String => LengthUnits(s, elt.runtimeData)
       case _ => throw new IllegalArgumentException("dfdl:%sLength's second argument must be one of the strings 'bits', 'bytes', or 'characters', but was: %s.".format(kind, str))
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
index f389744..3576e20 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
@@ -19,16 +19,17 @@ package org.apache.daffodil.dpath
 
 import java.lang.{ Long => JLong }
 
-import org.apache.daffodil.processors.unparsers.UnparseError
-import org.apache.daffodil.util.Maybe.Nope
-import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.infoset.XMLTextInfosetOutputter
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 import org.apache.daffodil.infoset.InfosetCommon
+import org.apache.daffodil.infoset.XMLTextInfosetOutputter
 import org.apache.daffodil.processors.parsers.PState
 import org.apache.daffodil.processors.parsers.ParseError
-import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.processors.unparsers.UState
+import org.apache.daffodil.processors.unparsers.UnparseError
+import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe.One
 
 case class DFDLXTrace(recipe: CompiledDPath, msg: String)
   extends RecipeOpWithSubRecipes(recipe) {
@@ -82,9 +83,9 @@ case object DAFError extends RecipeOp {
 case class DFDLXLookAhead(recipes: List[CompiledDPath])
   extends FNTwoArgs(recipes) {
 
-  def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    val offset = arg1.asInstanceOf[JLong]
-    val lBitSize = arg2.asInstanceOf[JLong]
+  def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    val offset = arg1.getLong
+    val lBitSize = arg2.getLong
 
     /*
      * Since dfdlx:lookAhead is defined to take unsigned arguements, the DPath interperater
@@ -124,7 +125,7 @@ case class DFDLXLookAhead(recipes: List[CompiledDPath])
       }
       val mark = dis.markPos
       dis.skip(offset, pstate)
-      val ans: AnyRef = if (bitSize > 63) {
+      val ans: DataValuePrimitive = if (bitSize > 63) {
         dis.getUnsignedBigInt(bitSize, pstate)
       } else if (bitSize == 0) {
         JLong.valueOf(0)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXTypeCalcFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXTypeCalcFunctions.scala
index a026362..c3bcc35 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXTypeCalcFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXTypeCalcFunctions.scala
@@ -17,14 +17,7 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.xml.QName
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.processors.TypeCalculator
-import org.apache.daffodil.processors.SimpleTypeRuntimeData
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.dpath.NodeInfo.PrimType.IntegerKind
-import org.apache.daffodil.dpath.NodeInfo.PrimType.String
-import org.apache.daffodil.dpath.NodeInfo.PrimType.Integer
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 import org.apache.daffodil.processors.TypeCalculator
 
 case class DFDLXInputTypeCalc(typedRecipes: List[(CompiledDPath, NodeInfo.Kind)], calc: TypeCalculator[AnyRef, AnyRef])
@@ -32,9 +25,9 @@ case class DFDLXInputTypeCalc(typedRecipes: List[(CompiledDPath, NodeInfo.Kind)]
 
   val srcType = typedRecipes(1)._2
 
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    calc.inputTypeCalcRun(dstate, arg2, srcType)
-    dstate.currentValue
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    calc.inputTypeCalcRun(dstate, arg2.getAnyRef, srcType)
+    dstate.currentValue.getNonNullable
   }
 
 }
@@ -44,9 +37,9 @@ case class DFDLXOutputTypeCalc(typedRecipes: List[(CompiledDPath, NodeInfo.Kind)
 
   val srcType = typedRecipes(1)._2
 
-  def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    calc.outputTypeCalcRun(dstate, arg2, srcType)
-    dstate.currentValue
+  def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    calc.outputTypeCalcRun(dstate, arg2.getAnyRef, srcType)
+    dstate.currentValue.getNonNullable
   }
 }
 
@@ -69,7 +62,7 @@ case class DFDLXOutputTypeCalcNextSibling(a: CompiledDPath, b: NodeInfo.Kind) ex
     val primType = nextSibling.erd.optPrimType.get
 
     val x = nextSibling.dataValue
-    typeCalculator.outputTypeCalcRun(dstate, x, primType)
+    typeCalculator.outputTypeCalcRun(dstate, x.getAnyRef, primType)
   }
 }
 
@@ -89,7 +82,7 @@ case class DFDLXRepTypeValue(a: CompiledDPath, b: NodeInfo.Kind)
      */
       dstate.SDE("dfdlx:repTypeValue() may only be called from within dfdlx:inputTypeCalc")
     }
-    dstate.setCurrentValue(dstate.repValue.get)
+    dstate.setCurrentValue(dstate.repValue)
   }
 }
 
@@ -110,6 +103,6 @@ case class DFDLXLogicalTypeValue(a: CompiledDPath, b: NodeInfo.Kind)
      */
       dstate.SDE("dfdlx:logicalTypeValue() may only be called from within dfdlx:outputTypeCalc")
     }
-    dstate.setCurrentValue(dstate.logicalValue.get)
+    dstate.setCurrentValue(dstate.logicalValue)
   }
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
index 004cae2..8e0bdf5 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
@@ -17,24 +17,44 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.exceptions._
-import org.apache.daffodil.util._
-import org.apache.daffodil.xml.NamedQName
-import org.apache.daffodil.processors._
-import org.apache.daffodil.infoset._
-import org.apache.daffodil.dsom._
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.calendar.DFDLCalendar
+import org.apache.daffodil.dsom.CompiledExpression
+import org.apache.daffodil.dsom.DPathCompileInfo
+import org.apache.daffodil.dsom.DPathElementCompileInfo
+import org.apache.daffodil.dsom.RuntimeSchemaDefinitionError
+import org.apache.daffodil.equality.EqualitySuppressUnusedImportWarning
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DIComplex
+import org.apache.daffodil.infoset.DIElement
+import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.infoset.InfosetArrayIndexOutOfBoundsException
+import org.apache.daffodil.infoset.InfosetException
+import org.apache.daffodil.infoset.InfosetLengthUnknownException
+import org.apache.daffodil.infoset.InfosetNoDataException
+import org.apache.daffodil.infoset.InfosetNoInfosetException
+import org.apache.daffodil.infoset.InfosetNoNextSiblingException
+import org.apache.daffodil.infoset.InfosetNoSuchChildElementException
+import org.apache.daffodil.infoset.InfosetNodeNotFinalException
+import org.apache.daffodil.infoset.OutputValueCalcEvaluationException
+import org.apache.daffodil.processors.CompileState
+import org.apache.daffodil.processors.Failure
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.ProcessingError
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.Suspension
+import org.apache.daffodil.processors.VariableException
 import org.apache.daffodil.processors.unparsers.UState
 import org.apache.daffodil.processors.unparsers.UnparseError
-import org.apache.daffodil.equality._; object EqualityNoWarn { EqualitySuppressUnusedImportWarning() }
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.xml.NamedQName; object EqualityNoWarn { EqualitySuppressUnusedImportWarning() }
 import org.apache.daffodil.api.DataLocation
 import org.apache.daffodil.api.Diagnostic
-import org.apache.daffodil.util.Numbers._
 import org.apache.daffodil.processors.parsers.DoSDEMixin
 import org.apache.daffodil.processors.parsers.PState
 import org.apache.daffodil.udf.UserDefinedFunctionProcessingErrorException
+import org.apache.daffodil.util.Numbers.asLong
 
 class ExpressionEvaluationException(e: Throwable, s: ParseOrUnparseState)
   extends ProcessingError(
@@ -159,12 +179,12 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
    * so as to detect deadlocks.
    */
   def evaluateForwardReferencing(state: ParseOrUnparseState, whereBlockedInfo: Suspension): Maybe[T] = {
-    var value: Maybe[AnyRef] = Nope
+    var value:Maybe[T] = Nope
     try {
       // TODO: This assumes a distinct state object (with its own dState) for every expression that
       // can be in evaluation simultaneously.
       val dstate = evaluateExpression(state, state.dState)
-      value = Maybe(processForwardExpressionResults(dstate))
+      value = One(processForwardExpressionResults(dstate))
       whereBlockedInfo.setDone
     } catch {
       case unfin: InfosetNodeNotFinalException =>
@@ -195,26 +215,26 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
     recipe.run(dstate)
   }
 
-  private def processForwardExpressionResults(dstate: DState): AnyRef = {
-    val v: AnyRef = {
+  private def processForwardExpressionResults(dstate: DState): T = {
+    val v = {
       dstate.currentNode match {
         case null => {
           // there is no element. Can happen if one evaluates say, 5 + 6 or 5 + $variable
-          Assert.invariant(dstate.currentValue != null)
-          dstate.currentValue
+          Assert.invariant(dstate.currentValue.isDefined)
+          dstate.currentValue.getAnyRef
         }
-        case n: DIElement if n.isNilled => n
+        case n: DIElement if n.isNilled => One(n)
         case c: DIComplex => {
           Assert.invariant(!targetType.isInstanceOf[NodeInfo.AnyAtomic.Kind])
           c
         }
         case s: DISimple => {
-          s.dataValue
+          s.dataValue.getAnyRef
         }
         case _ => Assert.invariantFailed("must be an element, simple or complex.")
       }
     }
-    v
+    v.asInstanceOf[T]
   }
 
   private def evaluateExpression(state: ParseOrUnparseState, dstate: DState): DState = {
@@ -234,11 +254,14 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
     val value =
       try {
         val dstate = evaluateExpression(state, state.dState)
-        processExpressionResults(dstate)
+        One(processExpressionResults(dstate))
       } catch {
-        case th: Throwable => handleThrow(th, state)
+        case th: Throwable => {
+          handleThrow(th, state)
+          Nope
+        }
       }
-    val value1 = postProcess(Maybe(value), state)
+    val value1 = postProcess(value, state)
     value1
   }
 
@@ -256,22 +279,22 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
   def isConstant = false
   def constant: T = Assert.usageError("Not a constant.")
 
-  private def processExpressionResults(dstate: DState): AnyRef = {
+  private def processExpressionResults(dstate: DState): T = {
     val v = {
       dstate.currentNode match {
         case null => {
           // there is no element. Can happen if one evaluates say, 5 + 6 in the debugger in which case
           // there is a value, but no node.
-          dstate.currentValue
+          dstate.currentValue.getAnyRef
         }
-        case n: DIElement if n.isNilled => n
+        case n: DIElement if n.isNilled => One
         case c: DIComplex => {
           Assert.invariant(!targetType.isInstanceOf[NodeInfo.AnyAtomic.Kind])
           c
         }
         case s: DISimple => {
           try {
-            s.dataValue
+            s.dataValue.getAnyRef
           } catch {
             case ovc: OutputValueCalcEvaluationException => {
               Assert.invariantFailed("OVC should always have a data value by the time it reaches here.")
@@ -281,7 +304,7 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
         case _ => Assert.invariantFailed("must be an element, simple or complex.")
       }
     }
-    v
+    v.asInstanceOf[T]
   }
 
   private def handleThrow(th: Throwable, state: ParseOrUnparseState): Null = {
@@ -324,7 +347,7 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kin
    * Note: Can't use a Maybe[T] here because T is required to be an AnyRef, and that would exclude
    * Long, Int, etc. from being used as values.
    */
-  private def postProcess(v: Maybe[AnyRef], state: ParseOrUnparseState): Maybe[T] = {
+  private def postProcess(v: Maybe[T], state: ParseOrUnparseState): Maybe[T] = {
     if (v.isEmpty) Nope
     else {
       val value = v.get
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
index e98f9bc..eaf0c18 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
@@ -20,13 +20,21 @@ package org.apache.daffodil.dpath
 import java.lang.{ Number => JNumber }
 import java.math.{ BigDecimal => JBigDecimal }
 import java.math.{ BigInteger => JBigInt }
+
 import scala.xml.NodeSeq.seqToNodeSeq
+
+import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.dsom.DPathCompileInfo
 import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
 import org.apache.daffodil.dsom.SchemaDefinitionError
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.SchemaFileLocation
 import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.infoset.DINode
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
+import org.apache.daffodil.infoset.DataValue.DataValueString
 import org.apache.daffodil.infoset.InfosetException
 import org.apache.daffodil.processors.CompileState
 import org.apache.daffodil.processors.ParseOrUnparseState
@@ -34,11 +42,6 @@ import org.apache.daffodil.processors.ProcessingError
 import org.apache.daffodil.processors.VariableException
 import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.util.Misc
-import org.apache.daffodil.dpath.NodeInfo.PrimType
-import org.apache.daffodil.dsom.DPathCompileInfo
-import org.apache.daffodil.xml.GlobalQName
-import org.apache.daffodil.processors.TypeCalculator
-import org.apache.daffodil.api.DaffodilTunables
 
 class CompiledDPath(val ops: RecipeOp*) extends Serializable {
 
@@ -78,7 +81,7 @@ class CompiledDPath(val ops: RecipeOp*) extends Serializable {
   def runExpressionForConstant(
     sfl: SchemaFileLocation,
     compileInfo: DPathCompileInfo,
-    tunable: DaffodilTunables): Option[AnyRef] = {
+    tunable: DaffodilTunables): DataValuePrimitiveNullable = {
 
     //
     // we use a special dummy dstate here that errors out via throw
@@ -90,7 +93,7 @@ class CompiledDPath(val ops: RecipeOp*) extends Serializable {
         run(dstate)
         // it ran, so must have produced a constant value
         val v = dstate.currentValue
-        Assert.invariant(v != null)
+        Assert.invariant(v.isDefined)
         // the only way dstate can have a value is if setCurrentValue was called
         // so this is redundant. Remove?
         // dstate.setCurrentValue(v) // side effect nulls out the current node
@@ -116,7 +119,7 @@ class CompiledDPath(val ops: RecipeOp*) extends Serializable {
         case e: ProcessingError => throw new SchemaDefinitionError(Some(sfl), None, e.getMessage())
       }
     val res =
-      if (isConstant) Some(dstate.currentValue) else None
+      if (isConstant) dstate.currentValue else DataValue.NoValue
     res
   }
 
@@ -186,7 +189,7 @@ case class VRef(vrd: VariableRuntimeData, context: ThrowsSDE)
 
 }
 
-case class Literal(v: AnyRef) extends RecipeOp {
+case class Literal(v: DataValuePrimitive) extends RecipeOp {
   override def run(dstate: DState) {
     dstate.setCurrentValue(v)
   }
@@ -200,7 +203,7 @@ case class IF(predRecipe: CompiledDPath, thenPartRecipe: CompiledDPath, elsePart
   override def run(dstate: DState) {
     val savedNode = dstate.currentNode
     predRecipe.run(dstate)
-    val predValue = dstate.currentValue.asInstanceOf[Boolean]
+    val predValue = dstate.currentValue.getBoolean
     dstate.setCurrentNode(savedNode)
     if (predValue) {
       thenPartRecipe.run(dstate)
@@ -209,7 +212,7 @@ case class IF(predRecipe: CompiledDPath, thenPartRecipe: CompiledDPath, elsePart
     }
     // should have a value now. IF-Then-Else is always
     // evaluated for a value.
-    Assert.invariant(dstate.currentValue != null)
+    Assert.invariant(dstate.currentValue.isDefined)
   }
 
   override def toXML =
@@ -237,10 +240,10 @@ case class CompareOperator(cop: CompareOpBase, left: CompiledDPath, right: Compi
   override def run(dstate: DState) {
     val savedNode = dstate.currentNode
     left.run(dstate)
-    val leftValue = dstate.currentValue
+    val leftValue = dstate.currentValue.getNonNullable
     dstate.setCurrentNode(savedNode)
     right.run(dstate)
-    val rightValue = dstate.currentValue
+    val rightValue = dstate.currentValue.getNonNullable
     val result = cop.operate(leftValue, rightValue)
     dstate.setCurrentValue(result)
   }
@@ -254,10 +257,10 @@ case class NumericOperator(nop: NumericOp, left: CompiledDPath, right: CompiledD
   override def run(dstate: DState) {
     val savedNode = dstate.currentNode
     left.run(dstate)
-    val leftValue = dstate.currentValue.asInstanceOf[JNumber]
+    val leftValue = dstate.currentValue.getNumber
     dstate.setCurrentNode(savedNode)
     right.run(dstate)
-    val rightValue = dstate.currentValue.asInstanceOf[JNumber]
+    val rightValue = dstate.currentValue.getNumber
     val result = nop.operate(leftValue, rightValue)
     dstate.setCurrentValue(result)
   }
@@ -288,7 +291,7 @@ abstract class Converter extends RecipeOp {
   }
 
   override def run(dstate: DState) {
-    val arg = dstate.currentValue
+    val arg = dstate.currentValue.getNonNullable
     val res =
       try {
         computeValue(arg, dstate)
@@ -298,16 +301,16 @@ abstract class Converter extends RecipeOp {
           val msg =
             if (e.getMessage() != null && e.getMessage() != "") e.getMessage()
             else "No other details are available."
-          val err = new NumberFormatException("Cannot convert '%s' from %s type to %s (%s).".format(arg.toString, fromTypeName, toTypeName, msg))
+          val err = new NumberFormatException("Cannot convert '%s' from %s type to %s (%s).".format(arg.getAnyRef.toString, fromTypeName, toTypeName, msg))
           throw err
         }
       }
     dstate.setCurrentValue(res)
   }
 
-  def computeValue(str: AnyRef, dstate: DState): AnyRef
+  def computeValue(str: DataValuePrimitive, dstate: DState): DataValuePrimitive
 }
 
 trait ToString extends Converter {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = a.toString
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueString = a.getAnyRef.toString
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
index 424aa10..bbd4e03 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
@@ -17,19 +17,34 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.processors._; import org.apache.daffodil.infoset._
-import org.apache.daffodil.exceptions._
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.calendar.DFDLCalendar
-import org.apache.daffodil.equality._; object EqualityNoWarn2 { EqualitySuppressUnusedImportWarning() }
+import org.apache.daffodil.equality.EqualitySuppressUnusedImportWarning
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.exceptions.SavesErrorsAndWarnings
+import org.apache.daffodil.infoset.DIArray
+import org.apache.daffodil.infoset.DIComplex
+import org.apache.daffodil.infoset.DIElement
+import org.apache.daffodil.infoset.DINode
+import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.FakeDINode
+import org.apache.daffodil.infoset.InfosetNoNextSiblingException
+import org.apache.daffodil.infoset.RetryableException
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.SchemaSetRuntimeData
+import org.apache.daffodil.processors.VariableBox
+import org.apache.daffodil.processors.VariableMap
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe.One; object EqualityNoWarn2 { EqualitySuppressUnusedImportWarning() }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+
+import org.apache.daffodil.api.DaffodilTunables
 import org.apache.daffodil.api.DataLocation
-import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
 import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.dsom.DPathCompileInfo
-import org.apache.daffodil.xml.GlobalQName
-import org.apache.daffodil.processors.TypeCalculatorCompiler.TypeCalcMap
-import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 
 /**
  * Modes for expression evaluation.
@@ -116,9 +131,9 @@ case class DState(
    * (eg. to the runtime stack), and replaces the below fields.
    * At the end of the computation, it should restore the below fields.
    */
-  var logicalValue: Maybe[AnyRef] = Maybe.Nope
+  var logicalValue: DataValuePrimitiveNullable = DataValue.NoValue
 
-  var repValue: Maybe[AnyRef] = Maybe.Nope
+  var repValue: DataValuePrimitiveNullable = DataValue.NoValue
 
   /**
    * The currentValue is used when we have a value that is not
@@ -126,7 +141,7 @@ case class DState(
    * the expression 5 + $x, then none of those literals, nor their
    * nor variable value, nor their sum, has an element associated with it.
    */
-  private var _currentValue: AnyRef = null
+  private var _currentValue: DataValuePrimitiveNullable = DataValue.NoValue
 
   private var _mode: EvalMode = ParserNonBlocking
 
@@ -184,39 +199,39 @@ case class DState(
   //  }
 
   def resetValue() {
-    _currentValue = null
+    _currentValue = DataValue.NoValue
   }
 
-  def currentValue: AnyRef = {
-    if (_currentValue eq null)
+  def currentValue: DataValuePrimitiveNullable = {
+    if (_currentValue.isEmpty)
       withRetryIfBlocking {
         currentSimple.dataValue
       }
     else _currentValue
   }
 
-  def setCurrentValue(v: AnyRef) {
+  def setCurrentValue(v: DataValuePrimitiveNullable) {
     _currentValue = v
     _currentNode = null
   }
   def setCurrentValue(v: Long) {
-    _currentValue = asAnyRef(v)
+    _currentValue = v
     _currentNode = null
   }
   def setCurrentValue(v: Boolean) {
-    _currentValue = asAnyRef(v)
+    _currentValue = v
     _currentNode = null
   }
 
-  def booleanValue: Boolean = currentValue.asInstanceOf[Boolean]
+  def booleanValue: Boolean = currentValue.getBoolean
 
-  def longValue: Long = asLong(currentValue)
+  def longValue: Long = asLong(currentValue.getAnyRef)
   def intValue: Int = longValue.toInt
-  def doubleValue: Double = asDouble(currentValue)
+  def doubleValue: Double = asDouble(currentValue.getAnyRef)
 
-  def integerValue: JBigInt = asBigInt(currentValue)
-  def decimalValue: JBigDecimal = asBigDecimal(currentValue)
-  def stringValue: String = currentValue.asInstanceOf[String]
+  def integerValue: JBigInt = asBigInt(currentValue.getAnyRef)
+  def decimalValue: JBigDecimal = asBigDecimal(currentValue.getAnyRef)
+  def stringValue: String = currentValue.getString
 
   def isNilled: Boolean = currentElement.isNilled
 
@@ -246,9 +261,9 @@ case class DState(
 
   def exists: Boolean = true // we're at a node, so it must exist.
 
-  def dateValue: DFDLCalendar = currentValue.asInstanceOf[DFDLCalendar]
-  def timeValue: DFDLCalendar = currentValue.asInstanceOf[DFDLCalendar]
-  def dateTimeValue: DFDLCalendar = currentValue.asInstanceOf[DFDLCalendar]
+  def dateValue: DFDLCalendar = currentValue.getCalendar
+  def timeValue: DFDLCalendar = currentValue.getCalendar
+  def dateTimeValue: DFDLCalendar = currentValue.getCalendar
 
   /**
    * Array index calculations (that is [expr], what XPath
@@ -261,7 +276,7 @@ case class DState(
   def currentNode = _currentNode
   def setCurrentNode(n: DINode) {
     _currentNode = n
-    _currentValue = null
+    _currentValue = DataValue.NoValue
   }
 
   def currentSimple = {
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNBases.scala
index 44fb70a..94406fd 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNBases.scala
@@ -17,16 +17,24 @@
 
 package org.apache.daffodil.dpath
 
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+
 import scala.collection.mutable.ListBuffer
 import scala.xml.NodeSeq.seqToNodeSeq
 
 import org.apache.daffodil.exceptions.Assert
-import java.lang.{ Integer => JInt, Long => JLong, Double => JDouble, Boolean => JBoolean }
-import java.math.{ BigInteger => JBigInt, BigDecimal => JBigDecimal }
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValueBool
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 import org.apache.daffodil.util.Numbers
 
 trait CompareOpBase {
-  def operate(v1: AnyRef, v2: AnyRef): AnyRef
+  def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValuePrimitive
 }
 
 trait NumberCompareOp extends CompareOpBase {
@@ -34,7 +42,7 @@ trait NumberCompareOp extends CompareOpBase {
    * It is such a pain that there is no scala.math.Number base class above
    * all the numeric types.
    */
-  def operate(v1: AnyRef, v2: AnyRef): JBoolean
+  override def operate(v1: DataValuePrimitive, v2: DataValuePrimitive): DataValueBool
 }
 
 trait StringCompareOp extends CompareOpBase {
@@ -47,7 +55,7 @@ trait StringCompareOp extends CompareOpBase {
    *
    * This mimics the fn:compare method closely.
    */
-  def compare(v1: AnyRef, v2: AnyRef): Int = v1.asInstanceOf[String].compare(v2.asInstanceOf[String])
+  def compare(v1: DataValuePrimitive, v2: DataValuePrimitive): Int = v1.getString.compare(v2.getString)
 }
 
 abstract class CompareOp
@@ -56,16 +64,16 @@ abstract class CompareOp
   override def run(dstate: DState) {
     val savedNode = dstate.currentNode
     left.run(dstate)
-    val leftValue = dstate.currentValue
+    val leftValue = dstate.currentValue.getNonNullable
     // Now reset back to the original node to evaluate the right
     dstate.setCurrentNode(savedNode)
     right.run(dstate)
-    val rightValue = dstate.currentValue
+    val rightValue = dstate.currentValue.getNonNullable
     val result = compare(op, leftValue, rightValue)
     dstate.setCurrentValue(result)
   }
 
-  def compare(op: String, v1: AnyRef, v2: AnyRef): JBoolean
+  def compare(op: String, v1: DataValuePrimitive, v2: DataValuePrimitive): JBoolean
 }
 
 case class BooleanOp(op: String, left: CompiledDPath, right: CompiledDPath)
@@ -73,7 +81,7 @@ case class BooleanOp(op: String, left: CompiledDPath, right: CompiledDPath)
   override def run(dstate: DState) {
     val savedNode = dstate.currentNode
     left.run(dstate)
-    val leftValue = dstate.currentValue.asInstanceOf[Boolean] // convertToBoolean(dstate.currentValue, dstate.pstate)
+    val leftValue = dstate.currentValue.getBoolean // convertToBoolean(dstate.currentValue, dstate.pstate)
 
     val result =
       if ((op == "and" && leftValue == false) ||
@@ -82,7 +90,7 @@ case class BooleanOp(op: String, left: CompiledDPath, right: CompiledDPath)
       } else {
         dstate.setCurrentNode(savedNode)
         right.run(dstate)
-        val rightValue = dstate.currentValue.asInstanceOf[Boolean] // convertToBoolean(dstate.currentValue, dstate.pstate)
+        val rightValue = dstate.currentValue.getBoolean // convertToBoolean(dstate.currentValue, dstate.pstate)
         rightValue
       }
 
@@ -92,10 +100,10 @@ case class BooleanOp(op: String, left: CompiledDPath, right: CompiledDPath)
 case class NegateOp(recipe: CompiledDPath) extends RecipeOpWithSubRecipes(recipe) {
   override def run(dstate: DState) {
     recipe.run(dstate)
-    val value: AnyRef = dstate.currentValue match {
-      case i: JInt => Numbers.asAnyRef(i * -1)
-      case l: JLong => Numbers.asAnyRef(l * (-1L))
-      case d: JDouble => Numbers.asAnyRef(d * -1.0)
+    val value: DataValuePrimitive = dstate.currentValue.getAnyRef match {
+      case i: JInt => i * -1
+      case l: JLong => l * -1L
+      case d: JDouble => d * -1.0
       case bi: JBigInt => bi.negate()
       case bd: JBigDecimal => bd.negate()
       case bi: BigInt => bi.underlying().negate()
@@ -112,13 +120,13 @@ abstract class FNOneArg(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends RecipeOpWithSubRecipes(recipe) {
   override def run(dstate: DState) {
     recipe.run(dstate)
-    val arg = dstate.currentValue
+    val arg = dstate.currentValue.getNonNullable
     dstate.setCurrentValue(computeValue(arg, dstate))
   }
 
   override def toXML = toXML(recipe.toXML)
 
-  def computeValue(str: AnyRef, dstate: DState): AnyRef
+  def computeValue(str: DataValuePrimitive, dstate: DState): DataValuePrimitive
 }
 
 abstract class FNTwoArgs(recipes: List[CompiledDPath])
@@ -131,18 +139,18 @@ abstract class FNTwoArgs(recipes: List[CompiledDPath])
     val savedNode = dstate.currentNode
     dstate.resetValue()
     recipe1.run(dstate)
-    val arg1 = dstate.currentValue
+    val arg1 = dstate.currentValue.getNonNullable
 
     dstate.setCurrentNode(savedNode)
     recipe2.run(dstate)
-    val arg2 = dstate.currentValue
+    val arg2 = dstate.currentValue.getNonNullable
 
     val res = computeValue(arg1, arg2, dstate)
     
     dstate.setCurrentValue(res)
   }
 
-  def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef
+  def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValuePrimitive
 
   override def toXML = toXML(recipes.map { _.toXML })
 }
@@ -161,12 +169,12 @@ abstract class FNTwoArgsNodeAndValue(recipes: List[CompiledDPath])
 
     dstate.setCurrentNode(savedNode)
     recipe2.run(dstate)
-    val arg2 = dstate.currentValue
+    val arg2 = dstate.currentValue.getNonNullable
 
     dstate.setCurrentValue(computeValue(arg1, arg2, dstate))
   }
 
-  def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef
+  def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValuePrimitive
 
   override def toXML = toXML(recipes.map { _.toXML })
 }
@@ -180,19 +188,19 @@ abstract class FNThreeArgs(recipes: List[CompiledDPath]) extends RecipeOpWithSub
 
     val savedNode = dstate.currentNode
     recipe1.run(dstate)
-    val arg1 = dstate.currentValue
+    val arg1 = dstate.currentValue.getNonNullable
 
     dstate.setCurrentNode(savedNode)
     recipe2.run(dstate)
-    val arg2 = dstate.currentValue
+    val arg2 = dstate.currentValue.getNonNullable
 
     dstate.setCurrentNode(savedNode)
     recipe3.run(dstate)
-    val arg3 = dstate.currentValue
+    val arg3 = dstate.currentValue.getNonNullable
     dstate.setCurrentValue(computeValue(arg1, arg2, arg3, dstate))
   }
 
-  def computeValue(arg1: AnyRef, arg2: AnyRef, arg3: AnyRef, dstate: DState): AnyRef
+  def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, arg3: DataValuePrimitive, dstate: DState): DataValuePrimitive
 
   override def toXML = toXML(recipes.map { _.toXML })
 }
@@ -204,12 +212,12 @@ abstract class FNArgsList(recipes: List[CompiledDPath]) extends RecipeOpWithSubR
 
     // FIXME: rewrite to use an OnStack ListBuffer, and
     // a while loop with index vs. the foreach.
-    val args: List[Any] = {
-      val list = new ListBuffer[Any]
+    val args: List[DataValuePrimitive] = {
+      val list = new ListBuffer[DataValuePrimitive]
 
       recipes.foreach { recipe =>
         recipe.run(dstate)
-        list += dstate.currentValue
+        list += dstate.currentValue.getNonNullable
         dstate.setCurrentNode(savedNode)
       }
       list.toList
@@ -218,5 +226,5 @@ abstract class FNArgsList(recipes: List[CompiledDPath]) extends RecipeOpWithSubR
     dstate.setCurrentValue(computeValue(args, dstate))
   }
 
-  def computeValue(args: List[Any], dstate: DState): AnyRef
+  def computeValue(args: List[DataValuePrimitive], dstate: DState): DataValuePrimitive
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
index 86b45df..46b4b58 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
@@ -17,33 +17,67 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.processors._; import org.apache.daffodil.infoset._
-import org.apache.daffodil.processors.unparsers.UnparseError
-import org.apache.daffodil.api.Diagnostic
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.math.RoundingMode
+
 import org.apache.daffodil.api.DataLocation
+import org.apache.daffodil.api.Diagnostic
+import org.apache.daffodil.calendar.DFDLCalendar
+import org.apache.daffodil.calendar.DFDLDate
+import org.apache.daffodil.calendar.DFDLDateTime
+import org.apache.daffodil.calendar.DFDLTime
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.exceptions.SchemaFileLocation
+import org.apache.daffodil.exceptions.UnsuppressableException
+import org.apache.daffodil.infoset.DIElement
+import org.apache.daffodil.infoset.DIFinalizable
+import org.apache.daffodil.infoset.DataValue.DataValueBigDecimal
+import org.apache.daffodil.infoset.DataValue.DataValueBool
+import org.apache.daffodil.infoset.DataValue.DataValueCalendar
+import org.apache.daffodil.infoset.DataValue.DataValueInt
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValueNumber
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueString
+import org.apache.daffodil.infoset.InfosetArrayIndexOutOfBoundsException
+import org.apache.daffodil.infoset.InfosetNoSuchChildElementException
+import org.apache.daffodil.infoset.InfosetNodeNotFinalException
+import org.apache.daffodil.infoset.InfosetWrongNodeType
+import org.apache.daffodil.infoset.RetryableException
+import org.apache.daffodil.processors.ProcessingError
+import org.apache.daffodil.processors.unparsers.UnparseError
 import org.apache.daffodil.util.Maybe
-import Maybe._
-import org.apache.daffodil.exceptions._
+import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.Numbers.asBigDecimal
+import org.apache.daffodil.util.Numbers.asBigInt
+import org.apache.daffodil.util.Numbers.asBoolean
+import org.apache.daffodil.util.Numbers.asByte
+import org.apache.daffodil.util.Numbers.asDouble
+import org.apache.daffodil.util.Numbers.asFloat
+import org.apache.daffodil.util.Numbers.asInt
+import org.apache.daffodil.util.Numbers.asLong
+import org.apache.daffodil.util.Numbers.asShort
+
 import com.ibm.icu.util.Calendar
-import java.math.RoundingMode
-import java.math.MathContext
 import com.ibm.icu.util.TimeZone
-import org.apache.daffodil.util.Numbers._
-import org.apache.daffodil.calendar.DFDLDateTime
-import org.apache.daffodil.calendar.DFDLCalendar
-import org.apache.daffodil.calendar.DFDLTime
-import org.apache.daffodil.calendar.DFDLDate
-import java.lang.{ Number => JNumber, Byte => JByte, Short => JShort, Integer => JInt, Long => JLong, Float => JFloat, Double => JDouble, Boolean => JBoolean }
-import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
 
 case class FNAbs(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(v: AnyRef, dstate: DState) = {
-    val value = asBigDecimal(v).abs
+  override def computeValue(v: DataValuePrimitive, dstate: DState) = {
+    val value = asBigDecimal(v.getAnyRef).abs
     argType match {
       case _: NodeInfo.UnsignedNumeric.Kind => value
       case NodeInfo.Decimal => value
-      case NodeInfo.Float => asAnyRef(asFloat(v).floatValue().abs)
-      case NodeInfo.Double => asAnyRef(asDouble(v).doubleValue().abs)
+      case NodeInfo.Float => asFloat(v.getAnyRef).floatValue().abs
+      case NodeInfo.Double => asDouble(v.getAnyRef).doubleValue().abs
       case NodeInfo.Long => asLong(value)
       case NodeInfo.Int => asInt(value)
       case NodeInfo.Integer => asBigInt(value)
@@ -55,32 +89,27 @@ case class FNAbs(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg
 }
 
 case class FNStringLength(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) = asAnyRef(str.asInstanceOf[String].length.toLong)
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueLong = str.getString.length.toLong
 }
 
 case class FNLowerCase(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) = str.asInstanceOf[String].toLowerCase
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueString = str.getString.toLowerCase
 }
 
 case class FNUpperCase(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(str: AnyRef, dstate: DState) = str.asInstanceOf[String].toUpperCase
+  override def computeValue(str: DataValuePrimitive, dstate: DState):DataValueString = str.getString.toUpperCase
 }
 
 case class FNConcat(recipes: List[CompiledDPath]) extends FNArgsList(recipes) {
-  override def computeValue(values: List[Any], dstate: DState) = values.mkString
+  override def computeValue(values: List[DataValuePrimitive], dstate: DState):DataValueString = {
+    val ans = new StringBuilder()
+    for(i <- 0 to values.length-1){
+      ans.append(values(i).getAnyRef.toString())
+    }
+    ans.toString()
+  }
 }
 
-// No such function in DFDL v1.0
-// But leave this here because we probably will want to add it as a
-// daffodil extension function and then eventually hope it gets into DFDL1.1
-//case class FNStringJoin(recipes: List[CompiledDPath]) extends FNTwoArgs(recipes) {
-//  override def computeValue(arg1: AnyRef, arg2:AnyRef, dstate: DState) = {
-//    val values = arg1.asInstanceOf[List[String]]
-//    val sep = arg2.asInstanceOf[String]
-//    values.mkString(sep)
-//  }
-//}
-
 trait SubstringKind {
 
   protected def substr(sourceString: String, startPos: Int, endPos: Int): String = {
@@ -166,9 +195,9 @@ case class FNSubstring2(recipes: List[CompiledDPath])
    *
    * fn:round(\$startingLoc) <= \$p < fn:round(INF)
    */
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    val sourceString = arg1.asInstanceOf[String]
-    val startingLoc = asDouble(arg2).doubleValue()
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueString = {
+    val sourceString = arg1.getString
+    val startingLoc = asDouble(arg2.getAnyRef).doubleValue()
     val length = Double.PositiveInfinity
 
     val res =
@@ -190,10 +219,10 @@ case class FNSubstring3(recipes: List[CompiledDPath])
    *
    * See: http://www.w3.org/TR/xpath-functions/#func-substring
    */
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, arg3: AnyRef, dstate: DState): AnyRef = {
-    val sourceString = arg1.asInstanceOf[String]
-    val startingLoc = asDouble(arg2)
-    val length = asDouble(arg3)
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, arg3: DataValuePrimitive, dstate: DState): DataValueString = {
+    val sourceString = arg1.getString
+    val startingLoc = asDouble(arg2.getAnyRef)
+    val length = asDouble(arg3.getAnyRef)
 
     substring(sourceString, startingLoc, length)
   }
@@ -203,9 +232,9 @@ case class FNSubstringBefore(recipes: List[CompiledDPath])
   extends FNTwoArgs(recipes)
   with SubstringKind {
 
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    val sourceString: String = arg1.asInstanceOf[String]
-    val searchString: String = arg2.asInstanceOf[String]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueString = {
+    val sourceString: String = arg1.getString
+    val searchString: String = arg2.getString
 
     val res =
       if (searchString == null || searchString == "") ""
@@ -222,9 +251,9 @@ case class FNSubstringAfter(recipes: List[CompiledDPath])
   extends FNTwoArgs(recipes)
   with SubstringKind {
 
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    val sourceString: String = arg1.asInstanceOf[String]
-    val searchString: String = arg2.asInstanceOf[String]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueString = {
+    val sourceString: String = arg1.getString
+    val searchString: String = arg2.getString
 
     val res =
       if (searchString == null || searchString == "") sourceString
@@ -249,9 +278,9 @@ case class FNDateTime(recipes: List[CompiledDPath]) extends FNTwoArgs(recipes) {
         dstate.SDE("Conversion Error: %s failed to convert \"%s\" to %s. Due to %s", fncName, calendar.toString, toType, ex.getMessage())
     }
   }
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState) = {
-    val dateCalendar = arg1.asInstanceOf[DFDLCalendar]
-    val timeCalendar = arg2.asInstanceOf[DFDLCalendar]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState):DataValueCalendar = {
+    val dateCalendar = arg1.getCalendar
+    val timeCalendar = arg2.getCalendar
 
     val dateCal = dateCalendar.calendar
     val timeCal = timeCalendar.calendar
@@ -310,7 +339,7 @@ case class FNRoundHalfToEven(recipeNum: CompiledDPath, recipePrecision: Compiled
     dstate.setCurrentNode(savedNode)
     recipePrecision.run(dstate)
     val precision = dstate.intValue
-    val bd = unrounded match {
+    val bd = unrounded.getAnyRef match {
       case s: String => BigDecimal(s) // TODO: Remove eventually. Holdover from JDOM where everything is a string.
       case l: JLong => BigDecimal.valueOf(l)
       case f: JFloat => BigDecimal.valueOf(f.toDouble)
@@ -343,7 +372,7 @@ trait FNRoundHalfToEvenKind {
    *
    * NOTE: Java does not appear to make a distinction between pos or neg zero.
    */
-  def compute(value: AnyRef, precision: Int) = {
+  def compute(value: DataValuePrimitive, precision: Int):DataValuePrimitive = {
     // We should only receive 'Numeric' types here which are either
     // xs:double, xs:float, xs:decimal, xs:integer or a sub-type thereof.
     //
@@ -351,12 +380,12 @@ trait FNRoundHalfToEvenKind {
     // have a serious issue.
     //
     def roundIt = {
-      val unroundedValue: JBigDecimal = unrounded(value)
+      val unroundedValue: DataValueBigDecimal = unrounded(value)
       val roundedValue = toBaseNumericType(round(unroundedValue, precision), value)
       roundedValue
     }
 
-    val result = value match {
+    val result:DataValuePrimitive = value.getAnyRef match {
       case f: JFloat if (f.isNaN() || f == 0 || f.floatValue().isPosInfinity || f.floatValue().isNegInfinity) => f
       case d: JDouble if (d.isNaN() || d == 0 || d.doubleValue().isPosInfinity || d.doubleValue().isNegInfinity) => d
       //
@@ -380,8 +409,8 @@ trait FNRoundHalfToEvenKind {
     result
   }
 
-  private def unrounded(value: AnyRef): java.math.BigDecimal = {
-    val result = value match {
+  private def unrounded(value: DataValuePrimitive): DataValueBigDecimal = {
+    val result = value.getAnyRef match {
       //
       // Not converting Float to string first causes precision issues
       // that round-half-to-even doesn't resolve correctly.  BigDecimal.valueOf(3.455) turns into 3.454999.
@@ -393,15 +422,15 @@ trait FNRoundHalfToEvenKind {
       // Any change in how asBigDecimal handles Float
       // will affect the correctness of this rounding operation.
       //
-      case _: JFloat | _: JDouble | _: BigDecimal | _: JBigDecimal => asBigDecimal(value)
-      case _: BigInt | _: JBigInt | _: JLong | _: JInt | _: JByte | _: JShort => asBigDecimal(value)
+      case _: JFloat | _: JDouble | _: BigDecimal | _: JBigDecimal => asBigDecimal(value.getAnyRef)
+      case _: BigInt | _: JBigInt | _: JLong | _: JInt | _: JByte | _: JShort => asBigDecimal(value.getAnyRef)
       case _ => Assert.usageError("Received a type other than xs:decimal, xs:double, xs:float, xs:integer or any of its sub-types.")
     }
     result
   }
 
-  private def round(value: JBigDecimal, precision: Int): JBigDecimal = {
-    val rounded: JBigDecimal = value.setScale(precision, RoundingMode.HALF_EVEN)
+  private def round(value: DataValueBigDecimal, precision: Int): DataValueBigDecimal = {
+    val rounded: JBigDecimal = value.getBigDecimal.setScale(precision, RoundingMode.HALF_EVEN)
     rounded
   }
 
@@ -412,18 +441,18 @@ trait FNRoundHalfToEvenKind {
    * If the type of \$arg is a type derived from one of the numeric types, the
    * result is an instance of the base numeric type.
    */
-  private def toBaseNumericType(value: JBigDecimal, origValue: AnyRef): AnyRef = {
-    val result = origValue match {
-      case _: JFloat => value.floatValue() // xs:float
-      case _: JDouble => value.doubleValue() // xs:double
+  private def toBaseNumericType(value: DataValueBigDecimal, origValue: DataValuePrimitive): DataValuePrimitive = {
+    val result:DataValuePrimitive = origValue.getAnyRef match {
+      case _: JFloat => value.getBigDecimal.floatValue() // xs:float
+      case _: JDouble => value.getBigDecimal.doubleValue() // xs:double
       case _: BigDecimal => value // xs:decimal
       case _: JBigDecimal => value
-      case _: BigInt => value.toBigInteger()
-      case _: JBigInt => value.toBigInteger()
-      case _: JLong | _: JInt | _: JByte | _: JShort => value.toBigInteger() // xs:integer
+      case _: BigInt => value.getBigDecimal.toBigInteger()
+      case _: JBigInt => value.getBigDecimal.toBigInteger()
+      case _: JLong | _: JInt | _: JByte | _: JShort => value.getBigDecimal.toBigInteger() // xs:integer
       case _ => Assert.usageError("Received a type other than xs:decimal, xs:double, xs:float, xs:integer or any of its sub-types.")
     }
-    asAnyRef(result)
+    result
   }
 
 }
@@ -443,7 +472,7 @@ case class FNRoundHalfToEven1(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType)
   with FNRoundHalfToEvenKind {
 
-  override def computeValue(value: AnyRef, dstate: DState) = {
+  override def computeValue(value: DataValuePrimitive, dstate: DState) = {
     val roundedValue = compute(value, 0)
     roundedValue
   }
@@ -463,8 +492,8 @@ case class FNRoundHalfToEven2(recipes: List[CompiledDPath])
   extends FNTwoArgs(recipes)
   with FNRoundHalfToEvenKind {
 
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState) = {
-    val precision = asInt(arg2)
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState) = {
+    val precision = asInt(arg2.getAnyRef)
     val roundedValue = compute(arg1, precision)
     roundedValue
   }
@@ -472,8 +501,8 @@ case class FNRoundHalfToEven2(recipes: List[CompiledDPath])
 
 case class FNNot(recipe: CompiledDPath, argType: NodeInfo.Kind = null)
   extends FNOneArg(recipe, NodeInfo.Boolean) {
-  override def computeValue(value: AnyRef, dstate: DState): JBoolean = {
-    val bool = asBoolean(FNToBoolean.computeValue(value, dstate))
+  override def computeValue(value: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val bool = asBoolean(FNToBoolean.computeValue(value, dstate).getAnyRef)
     !bool
   }
 }
@@ -652,7 +681,7 @@ case class FNLocalName0(recipe: CompiledDPath, argType: NodeInfo.Kind)
  */
 case class FNLocalName1(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
-  override def computeValue(value: AnyRef, dstate: DState) = {
+  override def computeValue(value: DataValuePrimitive, dstate: DState) = {
     Assert.usageError("not to be called. DPath compiler should be answering this without runtime calls.")
   }
 
@@ -681,38 +710,38 @@ case class FNLocalName1(recipe: CompiledDPath, argType: NodeInfo.Kind)
 }
 
 case class FNCeiling(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(value: AnyRef, dstate: DState) = argType match {
+  override def computeValue(value: DataValuePrimitive, dstate: DState) = argType match {
 
     case NodeInfo.Decimal => {
-      val bd = asBigDecimal(value)
+      val bd = asBigDecimal(value.getAnyRef)
       bd.setScale(0, RoundingMode.CEILING)
     }
-    case NodeInfo.Float => asAnyRef(asFloat(value).floatValue().ceil)
-    case NodeInfo.Double => asAnyRef(asDouble(value).floatValue().ceil)
+    case NodeInfo.Float => asFloat(value.getAnyRef).floatValue().ceil
+    case NodeInfo.Double => asDouble(value.getAnyRef).floatValue().ceil
     case _: NodeInfo.Numeric.Kind => value
     case _ => Assert.invariantFailed(String.format("Type %s is not a valid type for function ceiling.", argType))
   }
 }
 
 case class FNFloor(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(value: AnyRef, dstate: DState) = argType match {
+  override def computeValue(value: DataValuePrimitive, dstate: DState) = argType match {
 
     case NodeInfo.Decimal => {
-      val bd = asBigDecimal(value)
+      val bd = asBigDecimal(value.getAnyRef)
       bd.setScale(0, RoundingMode.FLOOR)
     }
-    case NodeInfo.Float => asAnyRef(asFloat(value).floatValue().floor)
-    case NodeInfo.Double => asAnyRef(asDouble(value).doubleValue().floor)
+    case NodeInfo.Float => asFloat(value.getAnyRef).floatValue().floor
+    case NodeInfo.Double => asDouble(value.getAnyRef).doubleValue().floor
     case _: NodeInfo.Numeric.Kind => value
     case _ => Assert.invariantFailed(String.format("Type %s is not a valid type for function floor.", argType))
   }
 }
 
 case class FNRound(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(value: AnyRef, dstate: DState) = {
-    val res = argType match {
+  override def computeValue(value: DataValuePrimitive, dstate: DState) = {
+    val res:DataValuePrimitive = argType match {
       case NodeInfo.Decimal => {
-        val bd = asBigDecimal(value)
+        val bd = asBigDecimal(value.getAnyRef)
         //
         // A MathContext object whose settings have
         // the values required for unlimited precision arithmetic.
@@ -720,21 +749,21 @@ case class FNRound(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneA
         bd.setScale(0, RoundingMode.HALF_UP)
       }
       case NodeInfo.Float => {
-        val f = asFloat(value).floatValue()
+        val f = asFloat(value.getAnyRef).floatValue()
         if (f.isPosInfinity || f.isNegInfinity) f
         else if (f.isNaN()) throw new NumberFormatException("fn:round received NaN")
-        else f.round
+        else f.round:Float
       }
       case NodeInfo.Double => {
-        val d = asDouble(value).doubleValue()
+        val d = asDouble(value.getAnyRef).doubleValue()
         if (d.isPosInfinity || d.isNegInfinity) d
         else if (d.isNaN()) throw new NumberFormatException("fn:round received NaN")
-        else d.round
+        else d.round:Double
       }
       case _: NodeInfo.Numeric.Kind => value
       case _ => Assert.invariantFailed(String.format("Type %s is not a valid type for function round.", argType))
     }
-    asAnyRef(res)
+    res
   }
 }
 
@@ -746,9 +775,9 @@ trait FNFromDateTimeKind {
 abstract class FNFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType)
   with FNFromDateTimeKind {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
-      case dt: DFDLDateTime => asAnyRef(dt.calendar.get(field))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    a.getAnyRef match {
+      case dt: DFDLDateTime => dt.calendar.get(field)
       case _ => throw new NumberFormatException("fn:" + fieldName + "-from-dateTime only accepts xs:dateTime.")
     }
   }
@@ -757,9 +786,9 @@ abstract class FNFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
 abstract class FNFromDate(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType)
   with FNFromDateTimeKind {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
-      case d: DFDLDate => asAnyRef(d.calendar.get(field))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt = {
+    a.getAnyRef match {
+      case d: DFDLDate => d.calendar.get(field)
       case _ => throw new NumberFormatException("fn:" + fieldName + "-from-date only accepts xs:date.")
     }
   }
@@ -768,9 +797,9 @@ abstract class FNFromDate(recipe: CompiledDPath, argType: NodeInfo.Kind)
 abstract class FNFromTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType)
   with FNFromDateTimeKind {
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    a match {
-      case t: DFDLTime => asAnyRef(t.calendar.get(field))
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValuePrimitive = {
+    a.getAnyRef match {
+      case t: DFDLTime => t.calendar.get(field)
       case _ => throw new NumberFormatException("fn:" + fieldName + "-from-time only accepts xs:time.")
     }
   }
@@ -785,7 +814,7 @@ case class FNMonthFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNFromDateTime(recipe, argType) {
   val fieldName = "month"
   val field = Calendar.MONTH
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asAnyRef(asInt(super.computeValue(a, dstate)).intValue() + 1) // JAN 0
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt = asInt(super.computeValue(a, dstate).getAnyRef).intValue() + 1 // JAN 0
 }
 case class FNDayFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNFromDateTime(recipe, argType) {
@@ -807,7 +836,7 @@ case class FNSecondsFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   val fieldName = "seconds"
   val field = Calendar.SECOND
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueNumber = {
     //
     // It matters that val res is declared to be type JNumber.
     //
@@ -824,7 +853,7 @@ case class FNSecondsFromDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
     // It seems to infer type Double for foo, and that squashes the polymorphism of
     // the number type, unless you explicitly make the val have type Any or Number.
     //
-    val res: JNumber = a match {
+    val res: JNumber = a.getAnyRef match {
       case dt: DFDLDateTime => {
         val seconds = dt.calendar.get(Calendar.SECOND)
         val frac = dt.calendar.get(Calendar.MILLISECOND)
@@ -849,7 +878,7 @@ case class FNMonthFromDate(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNFromDate(recipe, argType) {
   val fieldName = "month"
   val field = Calendar.MONTH
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = asAnyRef(asInt(super.computeValue(a, dstate)).intValue() + 1) // JAN 0
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt = asInt(super.computeValue(a, dstate).getAnyRef).intValue() + 1 // JAN 0
 }
 case class FNDayFromDate(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNFromDate(recipe, argType) {
@@ -870,13 +899,13 @@ case class FNSecondsFromTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNFromTime(recipe, argType) {
   val fieldName = "seconds"
   val field = Calendar.SECOND
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueNumber = {
     //
     // Please see the block comment in FNSecondsFromDateTime.computeValue
     //
     // It explains why val res below must be of type JNumber.
     //
-    val res: JNumber = a match {
+    val res: JNumber = a.getAnyRef match {
       case dt: DFDLTime => {
         val seconds = dt.calendar.get(Calendar.SECOND)
         val frac = dt.calendar.get(Calendar.MILLISECOND)
@@ -898,9 +927,9 @@ case class FNContains(recipes: List[CompiledDPath])
    * Returns an xs:boolean indicating whether or not the value of \$arg1 contains
    * (at the beginning, at the end, or anywhere within) \$arg2.
    */
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): JBoolean = {
-    val sourceString = arg1.asInstanceOf[String]
-    val valueString = arg2.asInstanceOf[String]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val sourceString = arg1.getString
+    val valueString = arg2.getString
 
     // If the value of \$arg2 is the zero-length string, then the function returns true.
     if (valueString.isEmpty()) return true
@@ -919,9 +948,9 @@ case class FNStartsWith(recipes: List[CompiledDPath])
    *  Returns an xs:boolean indicating whether or not the
    *  value of \$arg1 starts with \$arg2.
    */
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): JBoolean = {
-    val sourceString = arg1.asInstanceOf[String]
-    val prefixString = arg2.asInstanceOf[String]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val sourceString = arg1.getString
+    val prefixString = arg2.getString
 
     // If the value of \$arg2 is the zero-length string, then the function returns true.
     if (prefixString.isEmpty()) return true
@@ -941,9 +970,9 @@ case class FNEndsWith(recipes: List[CompiledDPath])
    * Returns an xs:boolean indicating whether or not the
    * value of \$arg1 ends with \$arg2.
    */
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): JBoolean = {
-    val sourceString = arg1.asInstanceOf[String]
-    val postfixString = arg2.asInstanceOf[String]
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueBool = {
+    val sourceString = arg1.getString
+    val postfixString = arg2.getString
 
     // If the value of \$arg2 is the zero-length string, then the function returns true.
     if (postfixString.isEmpty()) return true
@@ -967,7 +996,7 @@ case class FNErrorFunctionException(schemaContext: Maybe[SchemaFileLocation], da
   with FNErrorException
 
 case class FNError(recipes: List[CompiledDPath]) extends FNArgsList(recipes) {
-  override def computeValue(values: List[Any], dstate: DState) = {
+  override def computeValue(values: List[DataValuePrimitive], dstate: DState) = {
     val maybeSFL =
       if (dstate.runtimeData.isDefined) One(dstate.runtimeData.get.schemaFileLocation)
       else Nope
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/MATHFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/MATHFunctions.scala
index 0f0b3d6..81c8ad4 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/MATHFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/MATHFunctions.scala
@@ -19,11 +19,13 @@ package org.apache.daffodil.dpath
 
 import org.apache.daffodil.util.Numbers._
 import java.lang.{ Double => JDouble }
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueDouble
 
 case class MATHPow(recipes: List[CompiledDPath]) extends FNTwoArgs(recipes) {
-  override def computeValue(arg1: AnyRef, arg2: AnyRef, dstate: DState): AnyRef = {
-    val base = asDouble(arg1).doubleValue()
-    val exp = asDouble(arg2).doubleValue()
+  override def computeValue(arg1: DataValuePrimitive, arg2: DataValuePrimitive, dstate: DState): DataValueDouble = {
+    val base = asDouble(arg1.getAnyRef).doubleValue()
+    val exp = asDouble(arg2.getAnyRef).doubleValue()
     if (exp.isInfinite && (base == 1 || base == -1)) {
       // java pow(+-1, +-inf) returns NaN, XPath says it should be 1.0
       JDouble.valueOf(1.0)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NodeInfo.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NodeInfo.scala
index 0a9ab8a..70181e7 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NodeInfo.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NodeInfo.scala
@@ -17,22 +17,26 @@
 
 package org.apache.daffodil.dpath
 
-import java.lang.{ Boolean => JBoolean }
-import java.lang.{ Byte => JByte }
-import java.lang.{ Double => JDouble }
-import java.lang.{ Float => JFloat }
-import java.lang.{ Integer => JInt }
-import java.lang.{ Long => JLong }
-import java.lang.{ Short => JShort }
-import java.math.{ BigDecimal => JBigDecimal }
-import java.math.{ BigInteger => JBigInt }
+import java.lang.{ Boolean => JBoolean, Byte => JByte, Double => JDouble, Float => JFloat, Integer=> JInt, Long => JLong, Short => JShort }
+import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
 import java.net.URI
 
-import scala.BigDecimal
-import scala.BigInt
-
-import org.apache.daffodil.calendar._
+import org.apache.daffodil.calendar.DFDLCalendar
+import org.apache.daffodil.calendar.DFDLDateConversion
+import org.apache.daffodil.calendar.DFDLDateTimeConversion
+import org.apache.daffodil.calendar.DFDLTimeConversion
 import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DataValue.DataValueBool
+import org.apache.daffodil.infoset.DataValue.DataValueByte
+import org.apache.daffodil.infoset.DataValue.DataValueByteArray
+import org.apache.daffodil.infoset.DataValue.DataValueDate
+import org.apache.daffodil.infoset.DataValue.DataValueDateTime
+import org.apache.daffodil.infoset.DataValue.DataValueInt
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueShort
+import org.apache.daffodil.infoset.DataValue.DataValueTime
+import org.apache.daffodil.infoset.DataValue.DataValueURI
 import org.apache.daffodil.util.Enum
 import org.apache.daffodil.util.Misc
 import org.apache.daffodil.xml.GlobalQName
@@ -129,7 +133,7 @@ object NodeInfo extends Enum {
     def isError: Boolean = false
     def primType = this
 
-    def fromXMLString(s: String): AnyRef
+    def fromXMLString(s: String): DataValuePrimitive
   }
 
   private def getTypeNode(name: String) = {
@@ -480,25 +484,25 @@ object NodeInfo extends Enum {
     protected sealed trait LongKind extends Integer.Kind
     case object Long extends PrimTypeNode(Integer, List(Int)) with LongKind {
       type Kind = LongKind
-      override def fromXMLString(s: String): JLong = s.toLong
+      override def fromXMLString(s: String): DataValueLong = s.toLong
     }
 
     protected sealed trait IntKind extends Long.Kind
     case object Int extends PrimTypeNode(Long, List(Short)) with IntKind {
       type Kind = IntKind
-      override def fromXMLString(s: String): JInt = s.toInt
+      override def fromXMLString(s: String): DataValueInt = s.toInt
     }
 
     protected sealed trait ShortKind extends Int.Kind
     case object Short extends PrimTypeNode(Int, List(Byte)) with ShortKind {
       type Kind = ShortKind
-      override def fromXMLString(s: String): JShort = s.toShort
+      override def fromXMLString(s: String): DataValueShort = s.toShort
     }
 
     protected sealed trait ByteKind extends Short.Kind
     case object Byte extends PrimTypeNode(Short) with ByteKind {
       type Kind = ByteKind
-      override def fromXMLString(s: String): JByte = s.toByte
+      override def fromXMLString(s: String): DataValueByte = s.toByte
     }
 
     protected sealed trait NonNegativeIntegerKind extends Integer.Kind
@@ -518,21 +522,21 @@ object NodeInfo extends Enum {
     case object UnsignedInt extends PrimTypeNode(UnsignedLong, List(UnsignedShort, ArrayIndex)) with UnsignedIntKind {
       type Kind = UnsignedIntKind
       val Max = 4294967295L
-      override def fromXMLString(s: String): JLong = s.toLong
+      override def fromXMLString(s: String): DataValueLong = s.toLong
     }
 
     protected sealed trait UnsignedShortKind extends UnsignedInt.Kind
     case object UnsignedShort extends PrimTypeNode(UnsignedInt, List(UnsignedByte)) with UnsignedShortKind {
       type Kind = UnsignedShortKind
       val Max = 65535
-      override def fromXMLString(s: String): JInt = s.toInt
+      override def fromXMLString(s: String): DataValueInt = s.toInt
     }
 
     protected sealed trait UnsignedByteKind extends UnsignedShort.Kind
     case object UnsignedByte extends PrimTypeNode(UnsignedShort) with UnsignedByteKind {
       type Kind = UnsignedByteKind
       val Max = 255
-      override def fromXMLString(s: String): JShort = s.toShort
+      override def fromXMLString(s: String): DataValueShort = s.toShort
     }
 
     protected sealed trait StringKind extends AnyAtomic.Kind
@@ -544,25 +548,25 @@ object NodeInfo extends Enum {
     protected sealed trait BooleanKind extends AnySimpleType.Kind
     case object Boolean extends PrimTypeNode(AnyAtomic) with BooleanKind {
       type Kind = BooleanKind
-      override def fromXMLString(s: String): JBoolean = s.toBoolean
+      override def fromXMLString(s: String): DataValueBool = s.toBoolean
     }
 
     protected sealed trait AnyURIKind extends AnySimpleType.Kind
     case object AnyURI extends PrimTypeNode(AnyAtomic) with AnyURIKind {
       type Kind = AnyURIKind
-      override def fromXMLString(s: String): URI = new URI(s)
+      override def fromXMLString(s: String): DataValueURI = new URI(s)
     }
 
     protected sealed trait HexBinaryKind extends Opaque.Kind
     case object HexBinary extends PrimTypeNode(Opaque) with HexBinaryKind {
       type Kind = HexBinaryKind
-      override def fromXMLString(s: String): AnyRef = Misc.hex2Bytes(s)
+      override def fromXMLString(s: String): DataValueByteArray = Misc.hex2Bytes(s)
     }
 
     protected sealed trait DateKind extends AnyDateTimeKind
     case object Date extends PrimTypeNode(AnyDateTime) with DateKind {
       type Kind = DateKind
-      override def fromXMLString(s: String): AnyRef = {
+      override def fromXMLString(s: String): DataValueDate = {
         DFDLDateConversion.fromXMLString(s)
       }
     }
@@ -570,7 +574,7 @@ object NodeInfo extends Enum {
     protected sealed trait DateTimeKind extends AnyDateTimeKind
     case object DateTime extends PrimTypeNode(AnyDateTime) with DateTimeKind {
       type Kind = DateTimeKind
-      override def fromXMLString(s: String): AnyRef = {
+      override def fromXMLString(s: String): DataValueDateTime = {
         DFDLDateTimeConversion.fromXMLString(s)
       }
     }
@@ -578,7 +582,7 @@ object NodeInfo extends Enum {
     protected sealed trait TimeKind extends AnyDateTimeKind
     case object Time extends PrimTypeNode(AnyDateTime) with TimeKind {
       type Kind = TimeKind
-      override def fromXMLString(s: String): AnyRef = {
+      override def fromXMLString(s: String): DataValueTime = {
         DFDLTimeConversion.fromXMLString(s)
       }
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/SuspendableExpression.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/SuspendableExpression.scala
index 72d1b96..b8f039b 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/SuspendableExpression.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/SuspendableExpression.scala
@@ -17,12 +17,13 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.processors.unparsers.UState
 import org.apache.daffodil.dsom.CompiledExpression
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 import org.apache.daffodil.processors.Suspension
+import org.apache.daffodil.processors.unparsers.UState
 import org.apache.daffodil.util.LogLevel
 
 /**
@@ -40,10 +41,10 @@ trait SuspendableExpression
 
   override def toString = "SuspendableExpression(" + rd.diagnosticDebugName + ", expr=" + expr.prettyExpr + ")"
 
-  protected def processExpressionResult(ustate: UState, v: AnyRef): Unit
+  protected def processExpressionResult(ustate: UState, v: DataValuePrimitive): Unit
 
   override protected final def doTask(ustate: UState) {
-    var v: Maybe[AnyRef] = Nope
+    var v: DataValuePrimitiveNullable = DataValue.NoValue
     if (!isBlocked) {
       log(LogLevel.Debug, "Starting suspendable expression for %s, expr=%s", rd.diagnosticDebugName, expr.prettyExpr)
     } else {
@@ -51,7 +52,7 @@ trait SuspendableExpression
       log(LogLevel.Debug, "Retrying suspendable expression for %s, expr=%s", rd.diagnosticDebugName, expr.prettyExpr)
     }
     while (v.isEmpty && !this.isBlocked) {
-      v = expr.evaluateForwardReferencing(ustate, this)
+      v = DataValue.unsafeFromMaybeAnyRef(expr.evaluateForwardReferencing(ustate, this))
       if (v.isEmpty) {
         Assert.invariant(this.isBlocked)
         log(LogLevel.Debug, "UnparserBlocking suspendable expression for %s, expr=%s", rd.diagnosticDebugName, expr.prettyExpr)
@@ -59,7 +60,7 @@ trait SuspendableExpression
         Assert.invariant(this.isDone)
         Assert.invariant(ustate.currentInfosetNodeMaybe.isDefined)
         log(LogLevel.Debug, "Completed suspendable expression for %s, expr=%s", rd.diagnosticDebugName, expr.prettyExpr)
-        processExpressionResult(ustate, v.get)
+        processExpressionResult(ustate, v.getNonNullable)
       }
     }
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/UserDefinedFunctionBase.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/UserDefinedFunctionBase.scala
index 3ba2917..f79e3bf 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/UserDefinedFunctionBase.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/UserDefinedFunctionBase.scala
@@ -26,6 +26,8 @@ import org.apache.daffodil.udf.UserDefinedFunctionService.UserDefinedFunctionMet
 import java.lang.reflect.Method
 import java.lang.reflect.InvocationTargetException
 import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue
 
 /**
  * Both the serializable evaluate method and the User Defined Function instance are passed in,
@@ -38,11 +40,11 @@ case class UserDefinedFunctionCall(
   evaluateFxn: UserDefinedFunctionMethod)
   extends FNArgsList(recipes) {
 
-  override def computeValue(values: List[Any], dstate: DState) = {
-    val jValues = values.map { _.asInstanceOf[Object] }
+  override def computeValue(values: List[DataValuePrimitive], dstate: DState) = {
+    val jValues = values.map { _.getAnyRef.asInstanceOf[Object] }
     try {
       val res = evaluateFxn.method.invoke(userDefinedFunction, jValues: _*)
-      res
+      DataValue.unsafeFromAnyRef(res)
     } catch {
       case e: InvocationTargetException => {
         // wraps any error thrown by invoked method (i.e UDF.evaluate)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSConstructors.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSConstructors.scala
index 1046448..2bf7859 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSConstructors.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSConstructors.scala
@@ -17,25 +17,29 @@
 
 package org.apache.daffodil.dpath
 
-import org.apache.daffodil.util.Numbers._
 import org.apache.daffodil.calendar.DFDLDate
 import org.apache.daffodil.calendar.DFDLTime
+import org.apache.daffodil.infoset.DataValue.DataValueDate
+import org.apache.daffodil.infoset.DataValue.DataValueDateTime
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueString
+import org.apache.daffodil.infoset.DataValue.DataValueTime
+import org.apache.daffodil.util.Numbers.asInt
 
 case class XSInt(recipe: CompiledDPath) extends RecipeOpWithSubRecipes(recipe) {
   override def run(dstate: DState) {
     recipe.run(dstate)
     val basicValue = dstate.currentValue
-    val value = asInt(basicValue)
+    val value = asInt(basicValue.getAnyRef)
     dstate.setCurrentValue(value)
   }
 }
 
 case class XSString(recipe: CompiledDPath, argType: NodeInfo.Kind) extends FNOneArg(recipe, argType) {
-  override def computeValue(value: AnyRef, dstate: DState) = {
-    val res = value match {
+  override def computeValue(value: DataValuePrimitive, dstate: DState):DataValueString = {
+    val res:DataValueString = value.getAnyRef match {
       case hb: Array[Byte] => HexBinaryToString.computeValue(hb, dstate)
-      case _ =>
-        value.toString
+      case x => x.toString()
     }
     res
   }
@@ -45,8 +49,8 @@ case class XSDateTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
   val name = "XSDateTime"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDateTime = {
+    val result = a.getAnyRef match {
       case _: DFDLTime => throw new NumberFormatException("Casting from xs:time to xs:dateTime can never succeed.")
       case _ => StringToDateTime.computeValue(a, dstate)
     }
@@ -58,8 +62,8 @@ case class XSDate(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
   val name = "XSDate"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDate = {
+    val result = a.getAnyRef match {
       case _: DFDLTime => throw new NumberFormatException("Casting from xs:time to xs:date can never succeed.")
       case _ => StringToDate.computeValue(a, dstate)
     }
@@ -71,8 +75,8 @@ case class XSTime(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
   val name = "XSTime"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
-    val result = a match {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueTime = {
+    val result = a.getAnyRef match {
       case _: DFDLDate => throw new NumberFormatException("Casting from xs:date to xs:time can never succeed")
       case _ => StringToTime.computeValue(a, dstate)
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSHexBinary.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSHexBinary.scala
index b845106..ecfc5bb 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSHexBinary.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/XSHexBinary.scala
@@ -18,6 +18,8 @@
 package org.apache.daffodil.dpath
 
 import java.math.{ BigInteger => JBigInt, BigDecimal => JBigDecimal }
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValueByteArray
 
 trait HexBinaryKind {
 
@@ -89,7 +91,7 @@ case class XSHexBinary(recipe: CompiledDPath, argType: NodeInfo.Kind)
   extends FNOneArg(recipe, argType) {
   val name = "XSHexBinary"
 
-  override def computeValue(a: AnyRef, dstate: DState): AnyRef = {
+  override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueByteArray = {
     StringToHexBinary.computeValue(a, dstate)
   }
 }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
index ff01a4c..173e1cc 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
@@ -17,17 +17,16 @@
 
 package org.apache.daffodil.dsom
 
-import scala.runtime.ScalaRunTime.stringOf // for printing arrays properly.
+import scala.runtime.ScalaRunTime.stringOf
 
-import org.apache.daffodil.api.DaffodilTunables
 import org.apache.daffodil.api.UnqualifiedPathStepPolicy
 import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.dpath.DState
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
-import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.HasSchemaFileLocation
 import org.apache.daffodil.exceptions.SchemaFileLocation
+import org.apache.daffodil.infoset.DataValue
 import org.apache.daffodil.processors.ParseOrUnparseState
 import org.apache.daffodil.processors.RuntimeData
 import org.apache.daffodil.processors.Suspension
@@ -72,6 +71,8 @@ abstract class CompiledExpression[+T <: AnyRef](
   valueForDebugPrinting: AnyRef)
   extends ContentValueReferencedElementInfoMixin with Serializable {
 
+  DataValue.assertValueIsNotDataValue(valueForDebugPrinting)
+  
   final def toBriefXML(depth: Int = -1) = {
     "'" + prettyExpr + "'"
   }
@@ -147,10 +148,10 @@ final case class ConstantExpression[+T <: AnyRef](
   override def evaluate(state: ParseOrUnparseState) = value
 
   def evaluate(dstate: DState, state: ParseOrUnparseState) = {
-    dstate.setCurrentValue(value)
+    dstate.setCurrentValue(DataValue.unsafeFromAnyRef(value))
     value
   }
-  override def run(dstate: DState) = dstate.setCurrentValue(value)
+  override def run(dstate: DState) = dstate.setCurrentValue(DataValue.unsafeFromAnyRef(value))
 
   final def evaluateForwardReferencing(state: ParseOrUnparseState, whereBlockedLocation: Suspension): Maybe[T] = {
     // whereBlockedLocation is ignored since a constant expression cannot block.
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
index 099c06a..17b31d9 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
@@ -17,12 +17,13 @@
 
 package org.apache.daffodil.infoset
 
-import org.apache.daffodil.Implicits._;
-import org.apache.daffodil.xml.NS
-import org.apache.daffodil.util.MaybeBoolean
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.Implicits.ImplicitsSuppressUnusedImportWarning
 import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.MaybeBoolean
+import org.apache.daffodil.xml.NS
 
 object INoWarn2 { ImplicitsSuppressUnusedImportWarning() }
 
@@ -80,13 +81,13 @@ trait InfosetComplexElement extends InfosetElement {
 
 trait InfosetSimpleElement extends InfosetElement {
 
-  def dataValue: Any
+  def dataValue: DataValuePrimitiveNullable
 
   /**
    * Caches the string so we're not allocating strings just to do facet checks
    */
   def dataValueAsString: String
-  def setDataValue(s: AnyRef): Unit
+  def setDataValue(s: DataValuePrimitiveNullable): Unit
   def isDefaulted: Boolean
 }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
index c2dbdd6..cafb663 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
@@ -17,43 +17,52 @@
 
 package org.apache.daffodil.infoset
 
-import java.lang.{ Boolean => JBoolean, Number => JNumber }
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Number => JNumber }
 import java.math.{ BigDecimal => JBigDecimal }
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
-import org.apache.daffodil.util.MaybeInt
-import org.apache.daffodil.util.MaybeULong
+import java.util.HashMap
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.AtomicLong
+
+import scala.collection.IndexedSeq
 import scala.collection.mutable.ArrayBuffer
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.xml.NS
-import org.apache.daffodil.xml.XMLUtils
-import org.apache.daffodil.xml.NS
-import org.apache.daffodil.util.Misc
+
+import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.api.Diagnostic
+import org.apache.daffodil.calendar.DFDLCalendar
 import org.apache.daffodil.dpath.NodeInfo
-import org.apache.daffodil.xml.NamedQName
 import org.apache.daffodil.dsom.DPathElementCompileInfo
-import org.apache.daffodil.equality._
+import org.apache.daffodil.equality.TypeEqual
+import org.apache.daffodil.equality.ViewEqual
+import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.ThinThrowableWithCause
-import org.apache.daffodil.util.MaybeBoolean
-import scala.collection.IndexedSeq
-import org.apache.daffodil.util.Numbers._
-import org.apache.daffodil.util.MaybeULong
-import passera.unsigned.ULong
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 import org.apache.daffodil.io.DataOutputStream
 import org.apache.daffodil.io.DirectOrBufferedDataOutputStream
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.EvalCache
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.ProcessingError
+import org.apache.daffodil.processors.RuntimeData
+import org.apache.daffodil.processors.SimpleTypeRuntimeData
+import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.processors.parsers.PState
 import org.apache.daffodil.util.LogLevel
 import org.apache.daffodil.util.Logging
-import org.apache.daffodil.calendar.DFDLCalendar
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.concurrent.atomic.AtomicLong
-import org.apache.daffodil.api.Diagnostic
-import org.apache.daffodil.processors._
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.MaybeBoolean
+import org.apache.daffodil.util.MaybeInt
+import org.apache.daffodil.util.MaybeULong
+import org.apache.daffodil.util.Misc
 import org.apache.daffodil.util.Numbers
-import org.apache.daffodil.processors.ParseOrUnparseState
-import org.apache.daffodil.processors.parsers.PState
-import org.apache.daffodil.api.DaffodilTunables
-import java.util.HashMap
-import org.apache.daffodil.dsom.DPathElementCompileInfo
+import org.apache.daffodil.xml.NS
+import org.apache.daffodil.xml.NamedQName
+import org.apache.daffodil.xml.XMLUtils
+
+import passera.unsigned.ULong
 import org.apache.daffodil.dsom.DPathCompileInfo
 
 sealed trait DINode {
@@ -233,8 +242,8 @@ final class FakeDINode extends DISimple(null) {
   override def valid = die
   override def setValid(validity: Boolean): Unit = die
 
-  override def dataValue: AnyRef = _value
-  override def setDataValue(s: AnyRef): Unit = { _value = asAnyRef(s) }
+  override def dataValue: DataValuePrimitiveNullable = _value
+  override def setDataValue(s: DataValuePrimitiveNullable): Unit = { _value = s }
 
   override def dataValueAsString: String = _value.toString
   override def isDefaulted: Boolean = die
@@ -743,7 +752,7 @@ sealed trait DISimpleSharedMembersMixin {
 
   protected var _isDefaulted: Boolean = false
 
-  protected var _value: AnyRef = null
+  protected var _value: DataValuePrimitiveNullable = DataValue.NoValue
 
   protected var _unionMemberRuntimeData: Maybe[SimpleTypeRuntimeData] = Nope
 }
@@ -771,7 +780,7 @@ sealed trait DISimpleSharedImplMixin
   abstract override def clear() {
     super.clear()
     _isDefaulted = false
-    _value = null
+    _value = DataValue.NoValue
     _unionMemberRuntimeData = Nope
   }
 }
@@ -1066,7 +1075,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
 
   override def children: Stream[DINode] = Stream.Empty
 
-  def setDefaultedDataValue(defaultedValue: AnyRef) = {
+  def setDefaultedDataValue(defaultedValue: DataValuePrimitive) = {
     setDataValue(defaultedValue)
     _isDefaulted = true
   }
@@ -1081,12 +1090,12 @@ sealed class DISimple(override val erd: ElementRuntimeData)
    * Parsing of a text number first does setDataValue to a string, then a conversion does overwrite data value
    * with a number. Unparsing does setDataValue to a value, then overwriteDataValue to a string.
    */
-  override def setDataValue(x: AnyRef) {
+  override def setDataValue(x: DataValuePrimitiveNullable) {
     Assert.invariant(!hasValue)
     overwriteDataValue(x)
   }
 
-  def overwriteDataValue(x: AnyRef) {
+  def overwriteDataValue(x: DataValuePrimitiveNullable) {
     //
     // let's find places where we're putting a string in the infoset
     // but the simple type is not string. That happens when parsing or unparsing text Numbers, text booleans, text Date/Times.
@@ -1110,7 +1119,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
     // for converting to XML, or for debugging print statements.
     //
     val nodeKind = erd.optPrimType.get
-    x match {
+    x.getAnyRef match {
       case xs: String => {
         if (nodeKind.isInstanceOf[NodeInfo.String.Kind]) {
           // the value is a string, and the type of the node is string.
@@ -1130,7 +1139,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
           // So we set the stringRep, but not the value. (The value might be there if unparsing, or not if parsing)
           // When the converter runs, it will ask for the dataValueAsString which will take
           // the stringRep because we have defined it here.
-          _stringRep = x.asInstanceOf[String]
+          _stringRep = xs
         }
       }
       case _ => {
@@ -1144,7 +1153,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
         //
         _stringRep = null
         _bdRep = null
-        _value = x match {
+        _value = x.getAnyRef match {
           case dc: DFDLCalendar => dc
           case arb: Array[Byte] => arb
           case b: JBoolean => b
@@ -1179,7 +1188,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
     _unionMemberRuntimeData = Nope
     _stringRep = null
     _bdRep = null
-    _value = null
+    _value = DataValue.NoValue
   }
 
   /**
@@ -1189,47 +1198,47 @@ sealed class DISimple(override val erd: ElementRuntimeData)
   override def valueStringForDebug: String = {
     val res =
       if (_isNilled) "nil"
-      else if (_value ne null) _value.toString()
+      else if (_value.isDefined) _value.toString()
       else if (_stringRep ne null) "stringRep(" + _stringRep + ")"
       else ""
     res
   }
 
-  def hasValue: Boolean = !_isNilled && _value != null
+  def hasValue: Boolean = !_isNilled && _value.isDefined
   /**
    * Obtain the data value. Implements default
    * values, and outputValueCalc for unparsing.
    */
-  override def dataValue: AnyRef = {
-    if (_value == null)
+  override def dataValue: DataValuePrimitiveNullable = {
+    if (_value.isEmpty)
       if (erd.optDefaultValue.isDefined) {
-        val defaultVal = erd.optDefaultValue.get
-        if (defaultVal eq UseNilForDefault) {
+        val defaultVal = erd.optDefaultValue
+        if (defaultVal == DataValue.UseNilForDefault) {
           Assert.invariant(erd.isNillable)
           this.setNilled()
         } else {
-          _value = defaultVal
+          _value = defaultVal.getNullablePrimitive
         }
         _isDefaulted = true
       } else {
         erd.toss(new InfosetNoDataException(this, erd))
       }
-    if (_value == null) {
+    if (_value.isEmpty) {
       this.erd.schemaDefinitionError("Value has not been set.")
     }
-    _value
+    _value.getNonNullable
   }
 
-  final def maybeDataValue: Maybe[AnyRef] = {
-    val mv = if (_value ne null)
-      Maybe(_value)
+  final def maybeDataValue: DataValuePrimitiveNullable = {
+    val mv = if (_value.isDefined)
+      _value
     else if (erd.optDefaultValue.isDefined) {
-      val defaultVal = erd.optDefaultValue.get
-      _value = defaultVal
+      val defaultVal = erd.optDefaultValue
+      _value = defaultVal.getNullablePrimitive
       _isDefaulted = true
-      Maybe(_value)
+      _value
     } else {
-      Maybe.Nope
+      DataValue.NoValue
     }
     mv
   }
@@ -1237,7 +1246,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
   override def dataValueAsString = {
     if (_stringRep ne null) _stringRep
     else {
-      dataValue match {
+      dataValue.getAnyRef match {
         case s: String => s
         case arr: Array[Byte] => Misc.bytes2Hex(arr)
         case d: java.lang.Double => {
@@ -1253,7 +1262,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
           else if (f == Float.NegativeInfinity) XMLUtils.NegativeInfinityString
           else f.toString
         }
-        case _ => dataValue.toString
+        case x => x.toString
       }
     }
   }
@@ -1261,7 +1270,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
   def dataValueAsBigDecimal: JBigDecimal = {
     if (_bdRep ne null) _bdRep
     else {
-      dataValue match {
+      dataValue.getAnyRef match {
         case n: JBigDecimal => n
         case n: JNumber => Numbers.asJBigDecimal(n)
         case dc: DFDLCalendar => dc.toJBigDecimal
@@ -1283,7 +1292,7 @@ sealed class DISimple(override val erd: ElementRuntimeData)
       if (nodeKind =:= NodeInfo.String) {
         dataValueAsString.length =#= 0
       } else if (nodeKind =:= NodeInfo.HexBinary) {
-        dataValue.asInstanceOf[Array[Byte]].length =#= 0
+        dataValue.getByteArray.length =#= 0
       } else false
     }
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Evaluatable.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Evaluatable.scala
index 65116a3..79f3718 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Evaluatable.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Evaluatable.scala
@@ -39,6 +39,7 @@ import org.apache.daffodil.infoset._
 import org.apache.daffodil.processors.parsers.DoSDEMixin
 import org.apache.daffodil.processors.parsers.PState
 import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.dpath.RuntimeExpressionDPath
 import org.apache.daffodil.dsom.DPathCompileInfo
 import org.apache.daffodil.dsom.DPathElementCompileInfo
 
@@ -442,6 +443,7 @@ trait ExprEvalMixin[T <: AnyRef]
           }
         }
       }
+    DataValue.assertValueIsNotDataValue(expressionResult)
     expressionResult
   }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
index e527fa2..eb71513 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
@@ -18,48 +18,46 @@
 package org.apache.daffodil.processors
 
 import scala.xml.NamespaceBinding
+
+import org.apache.daffodil.Implicits.ImplicitsSuppressUnusedImportWarning
 import org.apache.daffodil.dpath.NodeInfo
-import org.apache.daffodil.dsom.DPathCompileInfo
-import org.apache.daffodil.dsom.ImplementsThrowsSDE
+import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.dsom.CompiledExpression
 import org.apache.daffodil.dsom.ConstantExpression
+import org.apache.daffodil.dsom.DPathCompileInfo
+import org.apache.daffodil.dsom.DPathElementCompileInfo
+import org.apache.daffodil.dsom.FacetTypes
+import org.apache.daffodil.dsom.ImplementsThrowsSDE
+import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.HasSchemaFileLocation
 import org.apache.daffodil.exceptions.SchemaFileLocation
+import org.apache.daffodil.exceptions.ThrowsSDE
+import org.apache.daffodil.infoset.PartialNextElementResolver
 import org.apache.daffodil.schema.annotation.props.gen.BitOrder
+import org.apache.daffodil.schema.annotation.props.gen.Representation
 import org.apache.daffodil.schema.annotation.props.gen.YesNo
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe.Nope
 import org.apache.daffodil.util.PreSerialization
 import org.apache.daffodil.util.TransientParam
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.xml.GlobalQName
-import org.apache.daffodil.xml.RefQName
-import org.apache.daffodil.schema.annotation.props.gen.BitOrder
+import org.apache.daffodil.xml.LocalDeclQName
 import org.apache.daffodil.xml.NS
-import org.apache.daffodil.dsom.FacetTypes
-import scala.xml.NamespaceBinding
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.util.Maybe._
-import org.apache.daffodil.xml._
-import org.apache.daffodil.dsom.DPathElementCompileInfo
-import org.apache.daffodil.dsom.CompiledExpression
-import org.apache.daffodil.schema.annotation.props.gen.Representation
-import org.apache.daffodil.exceptions.SchemaFileLocation
-import org.apache.daffodil.dpath.NodeInfo.PrimType
-import org.apache.daffodil.infoset.PartialNextElementResolver
-import org.apache.daffodil.util.TransientParam
-import org.apache.daffodil.schema.annotation.props.gen.YesNo
-import org.apache.daffodil.exceptions._
-import org.apache.daffodil.Implicits._; object NoWarn { ImplicitsSuppressUnusedImportWarning() }
-import org.apache.daffodil.infoset._
-import org.apache.daffodil.dpath.NodeInfo.PrimType
-import org.apache.daffodil.util.OKOrError
-import java.util.regex.Matcher
-import org.apache.daffodil.api.DaffodilTunables
-import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 import org.apache.daffodil.xml.NamedQName
+import org.apache.daffodil.xml.QNameBase
+import org.apache.daffodil.xml.RefQName
+import org.apache.daffodil.xml.StepQName; object NoWarn { ImplicitsSuppressUnusedImportWarning() }
+import java.util.regex.Matcher
+
+import org.apache.daffodil.api.UnqualifiedPathStepPolicy
+import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveOrUseNilForDefaultOrNull
 import org.apache.daffodil.processors.unparsers.UnparseError
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 import org.apache.daffodil.util.Misc
-import org.apache.daffodil.api.UnqualifiedPathStepPolicy
+import org.apache.daffodil.util.OKOrError
 
 /*
  * NOTE: Any time you add a member to one of these objects, you must modify at least 3 places.
@@ -254,7 +252,7 @@ final class SimpleTypeRuntimeData(
   extends NonTermRuntimeData(variableMapArg, schemaFileLocationArg, diagnosticDebugNameArg,
     pathArg, namespacesArg, unqualifiedPathStepPolicyArg) {
 
-  import OKOrError._
+  import org.apache.daffodil.util.OKOrError._
 
   lazy val primType = primTypeArg
   lazy val noFacetChecks = noFacetChecksArg
@@ -455,14 +453,14 @@ final class SimpleTypeRuntimeData(
     val minAsLong = minValue.longValueExact()
     primType match {
       case PrimType.String => {
-        val data = diNode.dataValue.asInstanceOf[String]
+        val data = diNode.dataValue.getString
         val dataLen = data.length.toLong
         val isDataLengthLess = dataLen.compareTo(minAsLong) < 0
         if (isDataLengthLess) java.lang.Boolean.FALSE
         else java.lang.Boolean.TRUE
       }
       case PrimType.HexBinary => {
-        val data = diNode.dataValue.asInstanceOf[Array[Byte]]
+        val data = diNode.dataValue.getByteArray
 
         val dataLen = data.length.toLong
         val isDataLengthEqual = dataLen.compareTo(minAsLong) == 0
@@ -478,14 +476,14 @@ final class SimpleTypeRuntimeData(
     val maxAsLong = maxValue.longValueExact()
     primType match {
       case PrimType.String => {
-        val data: String = diNode.dataValue.asInstanceOf[String]
+        val data: String = diNode.dataValue.getString
         val dataLen: Long = data.length.toLong
         val isDataLengthGreater = dataLen.compareTo(maxAsLong) > 0
         if (isDataLengthGreater) java.lang.Boolean.FALSE
         else java.lang.Boolean.TRUE
       }
       case PrimType.HexBinary => {
-        val data: Array[Byte] = diNode.dataValue.asInstanceOf[Array[Byte]]
+        val data: Array[Byte] = diNode.dataValue.getByteArray
         // Has to come through as a string in infoset
         // hex string is exactly twice as long as number of bytes
         // take length / 2 = length
@@ -655,7 +653,7 @@ sealed class ElementRuntimeData(
   @TransientParam hasNoSkipRegionsArg: => Boolean,
   @TransientParam impliedRepresentationArg: => Representation,
   @TransientParam optIgnoreCaseArg: => Option[YesNo],
-  @TransientParam optDefaultValueArg: => Option[AnyRef],
+  @TransientParam optDefaultValueArg: => DataValuePrimitiveOrUseNilForDefaultOrNull,
   //
   // Unparser-specific arguments
   //
@@ -841,7 +839,7 @@ sealed abstract class ErrorERD(local: String, namespaceURI: String)
     false, // hasNoSkipRegionsArg: => Boolean,
     null, // impliedRepresentationArg: => Representation,
     null, // optIgnoreCaseArg: => Option[YesNo],
-    null, // optDefaultValueArg: => Option[AnyRef],
+    DataValue.NoValue, // optDefaultValueArg: => DataValuePrimitiveOrUseNilForDefaultOrNull,
     null, // optTruncateSpecifiedLengthStringArg: => Option[Boolean],
     null, // outputValueCalcExprArg: => Option[CompiledExpression[AnyRef]],
     Nope, // maybeBinaryFloatRepEvArg: => Maybe[BinaryFloatRepEv],
@@ -1068,13 +1066,13 @@ final class VariableRuntimeData(
     if (!maybeDefaultValueExpr.isDefined) VariableUndefined
     else VariableDefined
 
-  private lazy val maybeValue: Maybe[AnyRef] =
-    if (maybeDefaultValueExpr.isEmpty) Nope
+  private lazy val maybeValue: DataValuePrimitiveNullable =
+    if (maybeDefaultValueExpr.isEmpty) DataValue.NoValue
     else {
       val defaultValueExpr = maybeDefaultValueExpr.get
       defaultValueExpr match {
-        case constExpr: ConstantExpression[_] => One(constExpr.constant.asInstanceOf[AnyRef])
-        case _ => Nope
+        case constExpr: ConstantExpression[_] => DataValue.unsafeFromAnyRef(constExpr.constant)
+        case _ => DataValue.NoValue
       }
     }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/TypeCalculator.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/TypeCalculator.scala
index 970a4e3..0121cc1 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/TypeCalculator.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/TypeCalculator.scala
@@ -24,6 +24,8 @@ import org.apache.daffodil.dpath.DState
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dsom.CompiledExpression
 import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 import org.apache.daffodil.processors.parsers.PState
 import org.apache.daffodil.processors.parsers.ParseError
 import org.apache.daffodil.processors.unparsers.UState
@@ -55,7 +57,7 @@ abstract class TypeCalculator[A <: AnyRef, B <: AnyRef](val srcType: NodeInfo.Ki
   def inputTypeCalc(x: A, xType: NodeInfo.Kind): (Maybe[B], Maybe[Error])
   def outputTypeCalc(x: B, xType: NodeInfo.Kind): (Maybe[A], Maybe[Error])
 
-  def inputTypeCalcParse(pstate: PState, context: RuntimeData, x: A, xType: NodeInfo.Kind): Maybe[B] = {
+  def inputTypeCalcParse(pstate: PState, context: RuntimeData, x: A, xType: NodeInfo.Kind): DataValuePrimitiveNullable = {
     val (ans, err) = inputTypeCalc(x, xType)
     Assert.invariant(ans.isDefined ^ err.isDefined)
 
@@ -66,7 +68,11 @@ abstract class TypeCalculator[A <: AnyRef, B <: AnyRef](val srcType: NodeInfo.Ki
 
     //In event of an error, we still want to return Maybe.Nope, which happens
     //to be what ans would have
-    ans
+    if(ans.isDefined){
+      DataValue.unsafeFromAnyRef(ans.get)
+    }else{
+      DataValue.NoValue
+    }
   }
   def outputTypeCalcUnparse(ustate: UState, context: RuntimeData, x: B, xType: NodeInfo.Kind): Maybe[A] = {
     val (ans, err) = outputTypeCalc(x, xType)
@@ -97,7 +103,7 @@ abstract class TypeCalculator[A <: AnyRef, B <: AnyRef](val srcType: NodeInfo.Ki
       //      throw FNErrorFunctionException(Maybe(context.schemaFileLocation), dstate.contextLocation, err.get)
     }
 
-    dstate.setCurrentValue(ans.get)
+    dstate.setCurrentValue(DataValue.unsafeFromAnyRef(ans.get))
 
   }
   def outputTypeCalcRun(dstate: DState, x: B, xType: NodeInfo.Kind): Unit = {
@@ -110,7 +116,7 @@ abstract class TypeCalculator[A <: AnyRef, B <: AnyRef](val srcType: NodeInfo.Ki
       throw diag
     }
 
-    dstate.setCurrentValue(ans.get)
+    dstate.setCurrentValue(DataValue.unsafeFromAnyRef(ans.get))
 
   }
 
@@ -210,25 +216,29 @@ class ExpressionTypeCalculator[A <: AnyRef, B <: AnyRef](
   override def outputTypeCalc(x: B, xType: NodeInfo.Kind): (Maybe[A], Maybe[Error]) =
     Assert.invariantFailed("outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly")
 
-  override def inputTypeCalcParse(state: PState, context: RuntimeData, x: A, xType: NodeInfo.Kind): Maybe[B] = {
+  override def inputTypeCalcParse(state: PState, context: RuntimeData, x: A, xType: NodeInfo.Kind): DataValuePrimitiveNullable = {
     val dstate = state.dState
     val oldRepValue = dstate.repValue
     val oldLogicalValue = dstate.logicalValue
-    dstate.repValue = One(x)
-    dstate.logicalValue = Maybe.Nope
+    dstate.repValue = DataValue.unsafeFromAnyRef(x)
+    dstate.logicalValue = DataValue.NoValue
 
     val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
 
     dstate.repValue = oldRepValue
     dstate.logicalValue = oldLogicalValue
-    ans
+    if(ans.isDefined){
+      DataValue.unsafeFromAnyRef(ans.get)
+    }else{
+      DataValue.NoValue;
+    }
   }
   override def outputTypeCalcUnparse(state: UState, context: RuntimeData, x: B, xType: NodeInfo.Kind): Maybe[A] = {
     val dstate = state.dState
     val oldRepValue = dstate.repValue
     val oldLogicalValue = dstate.logicalValue
-    dstate.repValue = Maybe.Nope
-    dstate.logicalValue = One(x)
+    dstate.repValue = DataValue.NoValue
+    dstate.logicalValue = DataValue.unsafeFromAnyRef(x)
 
     val ans = Maybe(maybeOutputTypeCalc.get.evaluate(state))
 
@@ -240,8 +250,8 @@ class ExpressionTypeCalculator[A <: AnyRef, B <: AnyRef](
   override def inputTypeCalcRun(dstate: DState, x: A, xType: NodeInfo.Kind): Unit = {
     val oldRepValue = dstate.repValue
     val oldLogicalValue = dstate.logicalValue
-    dstate.repValue = One(x)
-    dstate.logicalValue = Maybe.Nope
+    dstate.repValue = DataValue.unsafeFromAnyRef(x)
+    dstate.logicalValue = DataValue.NoValue
 
     maybeInputTypeCalc.get.run(dstate)
 
@@ -252,8 +262,8 @@ class ExpressionTypeCalculator[A <: AnyRef, B <: AnyRef](
   override def outputTypeCalcRun(dstate: DState, x: B, xType: NodeInfo.Kind): Unit = {
     val oldRepValue = dstate.repValue
     val oldLogicalValue = dstate.logicalValue
-    dstate.repValue = Maybe.Nope
-    dstate.logicalValue = One(x)
+    dstate.repValue = DataValue.NoValue
+    dstate.logicalValue = DataValue.unsafeFromAnyRef(x)
 
     maybeOutputTypeCalc.get.run(dstate)
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
index ebdb4f7..3f9150c 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
@@ -22,10 +22,12 @@ import org.apache.daffodil.dsom.CompiledExpression
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.externalvars.Binding
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 import org.apache.daffodil.infoset.RetryableException
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe.Nope
-import org.apache.daffodil.util.Maybe.One
 import org.apache.daffodil.xml.GlobalQName
 import org.apache.daffodil.xml.NamedQName
 
@@ -49,7 +51,7 @@ case object VariableInProcess extends VariableState
 /**
  * Core tuple of a pure functional "state" for variables.
  */
-case class Variable(state: VariableState, value: Maybe[AnyRef], rd: VariableRuntimeData, defaultValueExpr: Maybe[CompiledExpression[AnyRef]]) extends Serializable
+case class Variable(state: VariableState, value: DataValuePrimitiveNullable, rd: VariableRuntimeData, defaultValueExpr: Maybe[CompiledExpression[AnyRef]]) extends Serializable
 
 object VariableUtils {
 
@@ -65,7 +67,7 @@ object VariableUtils {
     newVMap
   }
 
-  def convert(v: String, rd: VariableRuntimeData): AnyRef =
+  def convert(v: String, rd: VariableRuntimeData): DataValuePrimitive =
     rd.primType.fromXMLString(v)
   // Infoset.convertToInfosetRepType(rd.primType, v, rd)
 }
@@ -185,7 +187,7 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
    * shows that the variable has been read (state VariableRead), when the variable hadn't
    * previously been read yet.
    */
-  def readVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE): (AnyRef, VariableMap) = {
+  def readVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE): (DataValuePrimitive, VariableMap) = {
     val referringContext: VariableRuntimeData = vrd
     val varQName = vrd.globalQName
     val lists = vTable.get(varQName)
@@ -194,12 +196,12 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
       case Some(firstTier :: enclosingScopes) =>
         firstTier match {
 
-          case Variable(VariableRead, v, ctxt, _) :: rest if (v.isDefined) => (v.get, this)
+          case Variable(VariableRead, v, ctxt, _) :: rest if (v.isDefined) => (v.getNonNullable, this)
 
           case Variable(st, v, ctxt, defExpr) :: rest if ((v.isDefined) && (st == VariableDefined || st == VariableSet)) => {
-            val newVar = Variable(VariableRead, One(v.get), ctxt, defExpr)
+            val newVar = Variable(VariableRead, v, ctxt, defExpr)
             val vmap = mkVMap(newVar, firstTier, enclosingScopes)
-            val converted = v.get // already converted
+            val converted = v.getNonNullable // already converted
             (converted, vmap)
           }
 
@@ -223,7 +225,7 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
   /**
    * Assigns a variable, returning a new VariableMap which shows the state of the variable.
    */
-  def setVariable(vrd: VariableRuntimeData, newValue: Any, referringContext: ThrowsSDE, pstate: ParseOrUnparseState): VariableMap = {
+  def setVariable(vrd: VariableRuntimeData, newValue: DataValuePrimitive, referringContext: ThrowsSDE, pstate: ParseOrUnparseState): VariableMap = {
     val varQName = vrd.globalQName
 
     vTable.get(varQName) match {
@@ -235,23 +237,23 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
         firstTier match {
 
           case Variable(VariableDefined, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
-            val newVar = Variable(VariableSet, One(VariableUtils.convert(newValue.toString, ctxt)), ctxt, defaultExpr)
+            val newVar = Variable(VariableSet, VariableUtils.convert(newValue.getAnyRef.toString, ctxt), ctxt, defaultExpr)
             mkVMap(newVar, firstTier, enclosingScopes)
           }
 
-          case Variable(VariableUndefined, Nope, ctxt, defaultExpr) :: rest => {
-            val newVar = Variable(VariableSet, One(VariableUtils.convert(newValue.toString, ctxt)), ctxt, defaultExpr)
+          case Variable(VariableUndefined, DataValue.NoValue, ctxt, defaultExpr) :: rest => {
+            val newVar = Variable(VariableSet, VariableUtils.convert(newValue.getAnyRef.toString, ctxt), ctxt, defaultExpr)
             mkVMap(newVar, firstTier, enclosingScopes)
           }
 
           case Variable(VariableSet, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
-            referringContext.SDE("Cannot set variable %s twice. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v.get)
+            referringContext.SDE("Cannot set variable %s twice. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v)
           }
 
           case Variable(VariableRead, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
             // referringContext.SDE
-            pstate.SDW("Cannot set variable %s after reading the default value. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v.get)
-            val newVar = Variable(VariableSet, One(VariableUtils.convert(newValue.toString, ctxt)), ctxt, defaultExpr)
+            pstate.SDW("Cannot set variable %s after reading the default value. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v)
+            val newVar = Variable(VariableSet, VariableUtils.convert(newValue.getAnyRef.toString, ctxt), ctxt, defaultExpr)
             mkVMap(newVar, firstTier, enclosingScopes)
           }
 
@@ -265,7 +267,7 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
   /**
    * Assigns a variable, returning a new VariableMap which shows the state of the variable.
    */
-  def setExtVariable(varQName: GlobalQName, newValue: Any, referringContext: ThrowsSDE): VariableMap = {
+  def setExtVariable(varQName: GlobalQName, newValue: DataValuePrimitive, referringContext: ThrowsSDE): VariableMap = {
     vTable.get(varQName) match {
 
       case None => referringContext.schemaDefinitionError("unknown variable %s", varQName)
@@ -275,22 +277,22 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
         firstTier match {
 
           case Variable(VariableDefined, v, ctxt, defaultExpr) :: rest if (v.isDefined && ctxt.external) => {
-            val newVar = Variable(VariableDefined, One(VariableUtils.convert(newValue.toString, ctxt)), ctxt, defaultExpr)
+            val newVar = Variable(VariableDefined, VariableUtils.convert(newValue.getAnyRef.toString, ctxt), ctxt, defaultExpr)
             val newFirstTier = newVar :: rest
             mkVMap(varQName, newFirstTier, enclosingScopes)
           }
           case Variable(VariableDefined, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
-            referringContext.SDE("Cannot set variable %s externally. State was: %s. Existing value: %s.", ctxt.globalQName, VariableDefined, v.get)
+            referringContext.SDE("Cannot set variable %s externally. State was: %s. Existing value: %s.", ctxt.globalQName, VariableDefined, v)
             // this // Unaltered VMap
           }
 
-          case Variable(VariableUndefined, Nope, ctxt, defaultExpr) :: rest if ctxt.external => {
-            val newVar = Variable(VariableDefined, One(VariableUtils.convert(newValue.toString, ctxt)), ctxt, defaultExpr)
+          case Variable(VariableUndefined, DataValue.NoValue, ctxt, defaultExpr) :: rest if ctxt.external => {
+            val newVar = Variable(VariableDefined, VariableUtils.convert(newValue.getAnyRef.toString, ctxt), ctxt, defaultExpr)
             val newFirstTier = newVar :: rest
             mkVMap(varQName, newFirstTier, enclosingScopes)
           }
 
-          case Variable(VariableUndefined, Nope, ctxt, defaultExpr) :: rest => {
+          case Variable(VariableUndefined, DataValue.NoValue, ctxt, defaultExpr) :: rest => {
             referringContext.SDE("Cannot set variable %s externally. State was: %s.", ctxt.globalQName, VariableUndefined)
             // this // Unaltered VMap
           }
@@ -298,12 +300,12 @@ class VariableMap private (vTable: Map[GlobalQName, List[List[Variable]]])
           case Variable(VariableSet, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
             // Shouldn't this be an impossible case? External variables should be defined before parsing.
             // Parsing is the only point at which Set can be called?
-            referringContext.SDE("Cannot externally set variable %s twice. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v.get)
+            referringContext.SDE("Cannot externally set variable %s twice. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v)
             // this // Unaltered VMap
           }
 
           case Variable(VariableRead, v, ctxt, defaultExpr) :: rest if (v.isDefined) => {
-            referringContext.SDE("Cannot externally set variable %s after reading the default value. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v.get)
+            referringContext.SDE("Cannot externally set variable %s after reading the default value. State was: %s. Existing value: %s", ctxt.globalQName, VariableSet, v)
             // this // Unaltered VMap
           }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
index 00d0421..21c1322 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
@@ -84,7 +84,7 @@ trait PrefixedLengthParserMixin {
       // evaluatable should check the processorStatus to see if anything
       // failed and ignore this zero. If there was no error, return the value
       // as a long.
-      if (state.processorStatus ne Success) 0 else Numbers.asLong(plElement.dataValue)
+      if (state.processorStatus ne Success) 0 else Numbers.asLong(plElement.dataValue.getAnyRef)
     } finally {
       // reset back to the original infoset and throw away the detatched
       // element
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
index 06c5ee4..0e686bd 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
@@ -259,7 +259,7 @@ class ChoiceDispatchCombinatorKeyByTypeParser(rd: TermRuntimeData, repTypeParser
   override def computeDispatchKey(pstate: PState): Maybe[String] = {
     val ans1 = runDetachedParser(pstate, repTypeParser, repTypeRuntimeData)
     if (ans1.isDefined) {
-      Maybe(ans1.get.toString())
+      Maybe(ans1.getAnyRef.toString())
     } else {
       Maybe.Nope
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
index 498e783..8f56a49 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
@@ -20,31 +20,19 @@ package org.apache.daffodil.processors.parsers
 import org.apache.daffodil.dpath.ParserDiscriminatorNonBlocking
 import org.apache.daffodil.dpath.ParserNonBlocking
 import org.apache.daffodil.dsom.CompiledExpression
-import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
 import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DataValue
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitiveNullable
 import org.apache.daffodil.infoset.InfosetSimpleElement
 import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.Evaluatable
 import org.apache.daffodil.processors.Failure
 import org.apache.daffodil.processors.RuntimeData
 import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.TypeCalculator
 import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.util.LogLevel
-import org.apache.daffodil.infoset.Infoset
-import org.apache.daffodil.processors.TypeCalculator
-import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.processors.Evaluatable
-import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.infoset.DIDocument
-import org.apache.daffodil.util.Maybe
-import org.apache.daffodil.infoset.DIComplexState
-import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.infoset.DIElement
-import org.apache.daffodil.infoset.DIDocument
-import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.processors.ElementRuntimeData
-import org.apache.daffodil.processors.Processor
 
 // import java.lang.{ Boolean => JBoolean }
 
@@ -63,8 +51,9 @@ abstract class ExpressionEvaluationParser(
   /**
    * Modifies the PState
    */
-  protected def eval(start: PState): AnyRef = {
-    expr.evaluate(start)
+  protected def eval(start: PState): DataValuePrimitive = {
+    val res = expr.evaluate(start)
+    DataValue.unsafeFromAnyRef(res)
   }
 }
 
@@ -91,7 +80,7 @@ class IVCParser(expr: CompiledExpression[AnyRef], e: ElementRuntimeData)
  * Additionally, the dataValue of the element the parser parsed will be returned
  */
 trait WithDetachedParser {
-  def runDetachedParser(pstate: PState, detachedParser: Parser, erd: ElementRuntimeData): Maybe[AnyRef] = {
+  def runDetachedParser(pstate: PState, detachedParser: Parser, erd: ElementRuntimeData): DataValuePrimitiveNullable = {
     /*
      * The parse1 being called here is that of ElementCombinator1, which expects to begin and end in the parent
      * of whatever element it is parsing. parse1 will create the new element and append it to the end of the
@@ -119,11 +108,11 @@ trait WithDetachedParser {
 
     val priorState = pstate.mark("WithDetachedParser.runDetachedParser: About to run detachedParser")
 
-    val ans: Maybe[AnyRef] = try {
+    val ans: DataValuePrimitiveNullable = try {
       detachedParser.parse1(pstate)
       pstate.processorStatus match {
-        case Success => Maybe(pstate.infoset.children.last.asSimple.dataValue)
-        case _       => None
+        case Success => pstate.infoset.children.last.asSimple.dataValue
+        case _       => DataValue.NoValue
       }
     } finally {
       //Restore the infoset, but keep any other side effects
@@ -142,15 +131,15 @@ class TypeValueCalcParser(typeCalculator: TypeCalculator[AnyRef, AnyRef], repTyp
   override lazy val runtimeDependencies: Vector[Evaluatable[AnyRef]] = Vector()
   
   override def parse(pstate: PState): Unit = {
-    val repValue: Maybe[AnyRef] = runDetachedParser(pstate, repTypeParser, repTypeRuntimeData)
+    val repValue: DataValuePrimitiveNullable = runDetachedParser(pstate, repTypeParser, repTypeRuntimeData)
     val repValueType = repTypeRuntimeData.optPrimType.get
     pstate.dataProc.get.ssrd
     if (pstate.processorStatus == Success) {
       Assert.invariant(repValue.isDefined)
-      val logicalValue: Maybe[AnyRef] = typeCalculator.inputTypeCalcParse(pstate, context, repValue.get, repValueType)
+      val logicalValue: DataValuePrimitiveNullable = typeCalculator.inputTypeCalcParse(pstate, context, repValue.getAnyRef, repValueType)
       if (pstate.processorStatus == Success) {
         Assert.invariant(logicalValue.isDefined)
-        pstate.simpleElement.setDataValue(logicalValue.get)
+        pstate.simpleElement.setDataValue(logicalValue)
       }
     }
   }
@@ -163,9 +152,6 @@ class SetVariableParser(expr: CompiledExpression[AnyRef], decl: VariableRuntimeD
   def parse(start: PState): Unit = {
     log(LogLevel.Debug, "This is %s", toString) // important. Don't toString unless we have to log.
     val res = eval(start)
-    res match {
-      case ps: PState => return ;
-      case _ => /*fall through*/ }
     if (start.processorStatus.isInstanceOf[Failure]) return
     // val vmap = start.variableMap
     start.setVariable(decl, res, decl, start)
@@ -228,7 +214,7 @@ class AssertExpressionEvaluationParser(
       // Assert.invariant(res != null)
       if (start.processorStatus ne Success) return
 
-      val testResult = res.asInstanceOf[Boolean]
+      val testResult = res.getBoolean
       if (testResult) {
         start.setDiscriminator(discrim)
       } else {
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
index 6484265..1e8f6b6 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
@@ -65,6 +65,7 @@ import org.apache.daffodil.infoset.DIComplexState
 import org.apache.daffodil.infoset.DISimpleState
 import org.apache.daffodil.exceptions.UnsuppressableException
 import org.apache.daffodil.exceptions.Abort
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 
 object MPState {
 
@@ -262,7 +263,7 @@ final class PState private (
     this.infoset = newParent
   }
 
-  def setVariable(vrd: VariableRuntimeData, newValue: Any, referringContext: VariableRuntimeData, pstate: PState) {
+  def setVariable(vrd: VariableRuntimeData, newValue: DataValuePrimitive, referringContext: VariableRuntimeData, pstate: PState) {
     this.setVariableMap(variableMap.setVariable(vrd, newValue, referringContext, pstate))
   }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildParseResultHelper.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildParseResultHelper.scala
index 2035ba3..1268454 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildParseResultHelper.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildParseResultHelper.scala
@@ -282,7 +282,7 @@ trait ElementSequenceChildParseResultHelper
                 ParseAttemptStatus.MissingItem
               }
               case EmptyElementParsePolicy.TreatAsEmpty => {
-                elem.dataValue match {
+                elem.dataValue.getAnyRef match {
                   case string: String if string.length == 0 => //ok
                   case byteArray: Array[Byte] if byteArray.length == 0 => //ok
                   case _ => Assert.invariant(!isZL) // must be nonZL empty rep.
diff --git a/eclipse-projects/runtime1/.classpath b/eclipse-projects/runtime1/.classpath
index e98663d..ab5d5a8 100644
--- a/eclipse-projects/runtime1/.classpath
+++ b/eclipse-projects/runtime1/.classpath
@@ -3,6 +3,7 @@
 <classpath>
   <!-- This file is updated by the UpdateEclipseClasspath app. -->
   <classpathentry kind="src" path="src/main/scala"/>
+  <classpathentry kind="src" path="src/main/scala-2.12"/>
   <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
   <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
   <classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>