Optimizing out the capture parser/unparsers for elements that have no
expressions referencing them via valueLength or contentLength

This means that for pcap parsing we should ONLY be calling the
capture parsers for content length or value length where absolutely
necessary.

For unparsing, note that there are a lot of reasons why we capture the value
region length however. E.g., alignment, mandatory text alignment are the two
real biggies.

Until we optimize out alignment and mandatory text alignment there are
still going to be a fair number of these capture processors put in by
the compiler.

Remove slow downcast on critical path.

Added pooling for DIElementState objects.

On demand creation and copying of ContentLengthState and
ValueLengthState objects.

Removed return statements from all repeating parse combinators. Hoping
this might improve performance a little. Removed try/finally from rep
parsers and alt-comp parser.

Removed println for debug left in on purpose in earlier commits.

DFDL-1610, DFDL-1613
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/compiler/Compiler.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/compiler/Compiler.scala
index 7eaa98d..6b79de0 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/compiler/Compiler.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/compiler/Compiler.scala
@@ -69,7 +69,6 @@
 import edu.illinois.ncsa.daffodil.schema.annotation.props.gen.ParseUnparsePolicy
 import edu.illinois.ncsa.daffodil.api.DaffodilTunableParameters
 
-
 /**
  * Some grammar rules need to be conditional based on whether we're trying
  * for a parser or an unparser.
@@ -91,6 +90,8 @@
   with DFDL.ProcessorFactory
   with HavingRootSpec {
 
+  final override def enclosingComponent: Option[SchemaComponentBase] = None
+
   lazy val (generateParser, generateUnparser) = {
     val (context, policy) =
       if (DaffodilTunableParameters.parseUnparsePolicy.isDefined) {
@@ -100,8 +101,8 @@
       }
     rootElem.checkParseUnparsePolicyCompatibility(context, policy)
     policy match {
-      case ParseUnparsePolicy.Both        => (true, true)
-      case ParseUnparsePolicy.ParseOnly   => (true, false)
+      case ParseUnparsePolicy.Both => (true, true)
+      case ParseUnparsePolicy.ParseOnly => (true, false)
       case ParseUnparsePolicy.UnparseOnly => (false, true)
     }
   }
@@ -268,18 +269,18 @@
       case "initialelementoccurrenceshint" => DaffodilTunableParameters.initialElementOccurrencesHint = java.lang.Long.valueOf(value)
       case "parseUnparsePolicy" => {
         val policy = value.toLowerCase match {
-          case "parseonly"   => Some(ParseUnparsePolicy.ParseOnly)
+          case "parseonly" => Some(ParseUnparsePolicy.ParseOnly)
           case "unparseonly" => Some(ParseUnparsePolicy.UnparseOnly)
-          case "both"        => Some(ParseUnparsePolicy.Both)
-          case "schema"      => None
+          case "both" => Some(ParseUnparsePolicy.Both)
+          case "schema" => None
           case _ => Assert.usageError("Unknown value for parseUnparsePolicy tunable. Value must be \"parseOnly\", \"unparseOnly\", \"both\", or \"schema\".")
         }
         DaffodilTunableParameters.parseUnparsePolicy = policy
       }
       case "unqualifiedpathsteppolicy" => {
         val policy = value.toLowerCase match {
-          case "nonamespace"            => DaffodilTunableParameters.UnqualifiedPathStepPolicy.NoNamespace
-          case "defaultnamespace"       => DaffodilTunableParameters.UnqualifiedPathStepPolicy.DefaultNamespace
+          case "nonamespace" => DaffodilTunableParameters.UnqualifiedPathStepPolicy.NoNamespace
+          case "defaultnamespace" => DaffodilTunableParameters.UnqualifiedPathStepPolicy.DefaultNamespace
           case "preferdefaultnamespace" => DaffodilTunableParameters.UnqualifiedPathStepPolicy.PreferDefaultNamespace
           case _ => Assert.usageError("Unknown value for unqualifiedPathStepPolicy tunable. Value must be \"noNamespace\", \"defaultNamespace\", or \"perferDefaultNamespace\".")
         }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DFDLExpressionParser.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DFDLExpressionParser.scala
index 337831a..8f8e8f0 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DFDLExpressionParser.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DFDLExpressionParser.scala
@@ -78,7 +78,10 @@
         res
       }
       case None => {
-        new RuntimeExpressionDPath[T](qn, nodeInfoKind, recipe, expr, context, isEvaluatedAbove)
+        val contentReferencedElementInfos = tree.contentReferencedElementInfos
+        val valueReferencedElementInfos = tree.valueReferencedElementInfos
+        new RuntimeExpressionDPath[T](qn, nodeInfoKind, recipe, expr, context, isEvaluatedAbove,
+          contentReferencedElementInfos, valueReferencedElementInfos)
       }
     }
     res
@@ -93,10 +96,10 @@
    *  Before this fix the following would occur:
    *
    *  Given:
-   * 	{ ../../e1 eq 1 }
+   *   { ../../e1 eq 1 }
    *
    *  Was interpreted as:
-   * 	{ ../../e1eq1 }
+   *   { ../../e1eq1 }
    *
    *  This was incorrect.
    */
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/Expression.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/Expression.scala
index 3191650..728dedf 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/Expression.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dpath/Expression.scala
@@ -66,6 +66,42 @@
   requiredEvaluations(isTypeCorrect)
   requiredEvaluations(compiledDPath_)
 
+  /**
+   * Override where we traverse/access elements.
+   */
+  def leafContentLengthReferencedElements = ReferencedElementInfos.None
+  def leafValueLengthReferencedElements = ReferencedElementInfos.None
+
+  def contentReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val clds = children
+    val cldsreis: Set[DPathElementCompileInfo] =
+      clds.foldLeft(ReferencedElementInfos.None) {
+        (s, item) =>
+          {
+            val ireis = item.contentReferencedElementInfos
+            s.union(ireis)
+          }
+      }
+    val res = cldsreis ++
+      leafContentLengthReferencedElements
+    res
+  }
+
+  def valueReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val clds = children
+    val cldsreis: Set[DPathElementCompileInfo] =
+      clds.foldLeft(ReferencedElementInfos.None) {
+        (s, item) =>
+          {
+            val ireis = item.valueReferencedElementInfos
+            s.union(ireis)
+          }
+      }
+    val res = cldsreis ++
+      leafValueLengthReferencedElements
+    res
+  }
+
   // This split allows overrides of this lazy val to still reuse this
   // (super.isTypeCorrect doesn't work inside an overridden lazy val.)
   lazy val isTypeCorrect: Boolean = checkTypeCorrectness
@@ -1118,7 +1154,7 @@
   }
 
   override def toString = text
-  
+
   def isValidInt(n: Number): Boolean = {
     val bd = new JBigDecimal(n.toString())
     val res = try {
@@ -1129,7 +1165,7 @@
     }
     res
   }
-  
+
   def isValidLong(n: Number): Boolean = {
     val bd = new JBigDecimal(n.toString())
     val res = try {
@@ -1140,7 +1176,7 @@
     }
     res
   }
-  
+
   def isDecimalDouble(bd: JBigDecimal): Boolean = {
     val d = bd.doubleValue()
     !d.isInfinity && equals(bd)
@@ -1255,6 +1291,9 @@
 
   override def text = functionObject.text
 
+  final override def leafContentLengthReferencedElements = functionObject.leafContentLengthReferencedElements
+  final override def leafValueLengthReferencedElements = functionObject.leafValueLengthReferencedElements
+
   lazy val functionQName: RefQName = resolveRef(functionQNameString)
 
   override lazy val compiledDPath = functionObject.compiledDPath
@@ -1486,7 +1525,7 @@
       }
 
       case (RefQName(_, "contentLength", DFDL), args) =>
-        FNTwoArgsExpr(functionQNameString, functionQName, args,
+        ContentLengthExpr(functionQNameString, functionQName, args,
           NodeInfo.Long, NodeInfo.Exists, NodeInfo.String, DFDLContentLength(_))
       // The above specifies Exists, because we want to know a node exists, but
       // it has to be a node, not a simple value. E.g., dfdl:contentLength("foobar", "bits") makes no sense.
@@ -1497,7 +1536,7 @@
       // But that's fairly pointless.
 
       case (RefQName(_, "valueLength", DFDL), args) => {
-        FNTwoArgsExpr(functionQNameString, functionQName, args,
+        ValueLengthExpr(functionQNameString, functionQName, args,
           NodeInfo.Long, NodeInfo.Exists, NodeInfo.String, DFDLValueLength(_))
       }
 
@@ -1775,7 +1814,7 @@
   }
 }
 
-case class FNTwoArgsExpr(nameAsParsed: String, fnQName: RefQName,
+abstract class FNTwoArgsExprBase(nameAsParsed: String, fnQName: RefQName,
   args: List[Expression], resultType: NodeInfo.Kind, arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind,
   constructor: List[CompiledDPath] => RecipeOp)
   extends FunctionCallBase(nameAsParsed, fnQName, args) {
@@ -1801,6 +1840,44 @@
   }
 }
 
+case class FNTwoArgsExpr(nameAsParsed: String, fnQName: RefQName,
+  args: List[Expression], resultType: NodeInfo.Kind, arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind,
+  constructor: List[CompiledDPath] => RecipeOp)
+  extends FNTwoArgsExprBase(nameAsParsed, fnQName, args, resultType, arg1Type, arg2Type, constructor)
+
+sealed abstract class LengthExprBase(nameAsParsed: String, fnQName: RefQName,
+  args: List[Expression], resultType: NodeInfo.Kind, arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind,
+  constructor: List[CompiledDPath] => RecipeOp)
+  extends FNTwoArgsExprBase(nameAsParsed, fnQName, args, resultType, arg1Type, arg2Type, constructor) {
+
+  protected final def leafReferencedElements = {
+       val arg = args(0).asInstanceOf[PathExpression]
+    val steps = arg.steps
+    val lst = steps.last
+    val elem = lst.stepElement
+    val res = Set(elem)
+    res
+  }
+
+}
+
+case class ContentLengthExpr(nameAsParsed: String, fnQName: RefQName,
+  args: List[Expression], resultType: NodeInfo.Kind, arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind,
+  constructor: List[CompiledDPath] => RecipeOp)
+  extends LengthExprBase(nameAsParsed, fnQName, args, resultType, arg1Type, arg2Type, constructor) {
+
+    override lazy val leafContentLengthReferencedElements = leafReferencedElements
+}
+
+
+case class ValueLengthExpr(nameAsParsed: String, fnQName: RefQName,
+  args: List[Expression], resultType: NodeInfo.Kind, arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind,
+  constructor: List[CompiledDPath] => RecipeOp)
+  extends LengthExprBase(nameAsParsed, fnQName, args, resultType, arg1Type, arg2Type, constructor) {
+
+    override lazy val leafValueLengthReferencedElements = leafReferencedElements
+}
+
 case class FNThreeArgsExpr(nameAsParsed: String, fnQName: RefQName,
   args: List[Expression], resultType: NodeInfo.Kind,
   arg1Type: NodeInfo.Kind, arg2Type: NodeInfo.Kind, arg3Type: NodeInfo.Kind,
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/AnnotatedSchemaComponent.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/AnnotatedSchemaComponent.scala
index 0b2745a..6220722 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/AnnotatedSchemaComponent.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/AnnotatedSchemaComponent.scala
@@ -198,7 +198,10 @@
     val dais = ais.filter { ai =>
       {
         ai.attribute("source") match {
-          case None => false
+          case None => {
+            this.SDW("""xs:appinfo without source attribute. Is source="http://www.ogf.org/dfdl/" missing?""")
+            false
+          }
           case Some(n) => {
             val sourceNS = NS(n.text)
             //
@@ -232,9 +235,9 @@
    * The DFDL annotations on the component, as objects
    * that are subtypes of DFDLAnnotation.
    */
-  final def annotationObjs = LV('annotationObjs) {
+  final lazy val annotationObjs = {
     // println(dais)
-    dais.flatMap { dai =>
+    val objs = dais.flatMap { dai =>
       {
         val children = dai.child
         val res = children.filter { _.isInstanceOf[scala.xml.Elem] }.flatMap { child =>
@@ -245,7 +248,8 @@
         res
       }
     }
-  }.value
+    objs
+  }
 
   /**
    * Here we establish an invariant which is that every annotatable schema component has, definitely, has an
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ComplexTypes.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ComplexTypes.scala
index 066677e..0f596d3 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ComplexTypes.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ComplexTypes.scala
@@ -2,25 +2,25 @@
  *
  * Developed by: Tresys Technology, LLC
  *               http://www.tresys.com
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  * this software and associated documentation files (the "Software"), to deal with
  * the Software without restriction, including without limitation the rights to
  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  * of the Software, and to permit persons to whom the Software is furnished to do
  * so, subject to the following conditions:
- * 
+ *
  *  1. Redistributions of source code must retain the above copyright notice,
  *     this list of conditions and the following disclaimers.
- * 
+ *
  *  2. Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimers in the
  *     documentation and/or other materials provided with the distribution.
- * 
+ *
  *  3. Neither the names of Tresys Technology, nor the names of its contributors
  *     may be used to endorse or promote products derived from this Software
  *     without specific prior written permission.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -37,9 +37,9 @@
 import edu.illinois.ncsa.daffodil.dpath.NodeInfo
 
 abstract class ComplexTypeBase(xmlArg: Node, parent: SchemaComponent)
-    extends SchemaComponent(xmlArg, parent)
-    with TypeBase
-    with ComplexTypeBaseGrammarMixin {
+  extends SchemaComponent(xmlArg, parent)
+  with TypeBase
+  with ComplexTypeBaseGrammarMixin {
 
   requiredEvaluations(modelGroup)
 
@@ -102,7 +102,7 @@
 }
 
 final class GlobalComplexTypeDefFactory(xmlArg: Node, schemaDocumentArg: SchemaDocument)
-    extends SchemaComponent(xmlArg, schemaDocumentArg) with NamedMixin {
+  extends SchemaComponent(xmlArg, schemaDocumentArg) with NamedMixin {
 
   def forElement(element: ElementBase) = new GlobalComplexTypeDef(xml, schemaDocument, element)
 
@@ -112,15 +112,15 @@
  * For unit testing purposes, the element argument might be supplied as null.
  */
 final class GlobalComplexTypeDef(xmlArg: Node, schemaDocumentArg: SchemaDocument, val element: ElementBase)
-    extends ComplexTypeBase(xmlArg, schemaDocumentArg)
-    with GlobalComponentMixin {
+  extends ComplexTypeBase(xmlArg, schemaDocumentArg)
+  with GlobalComponentMixin {
 
   lazy val referringComponent = Option(element)
 
 }
 
 final class LocalComplexTypeDef(xmlArg: Node, val element: ElementBase)
-    extends ComplexTypeBase(xmlArg, element)
-    with LocalComponentMixin {
+  extends ComplexTypeBase(xmlArg, element)
+  with LocalComponentMixin {
   //nothing
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLAssertion.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLAssertion.scala
index 9c698f4..af5cb9f 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLAssertion.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLAssertion.scala
@@ -63,7 +63,7 @@
     case s if (s.trim().length() == 0) => None
     case txt => Some(txt.trim())
   } // package visible for unit testing
-
+  
   private lazy val testPattern = {
     val optPattern = getAttributeOption("testPattern")
     if (optPattern.isDefined) {
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLDefineVariable.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLDefineVariable.scala
index 7bca3c3..91f5acd 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLDefineVariable.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLDefineVariable.scala
@@ -82,7 +82,7 @@
 
   final override lazy val runtimeData = variableRuntimeData
 
-  private lazy val maybeDefaultValueExpr = {
+  lazy val maybeDefaultValueExpr = {
     val compilationTargetType = primType
     val qn = this.qNameForProperty("defaultValue", XMLUtils.dafintURI)
     val defaultValExpr = defaultValue.map { e =>
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLEscapeScheme.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLEscapeScheme.scala
index ddab6c4..884ad98 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLEscapeScheme.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLEscapeScheme.scala
@@ -53,7 +53,7 @@
   with EscapeScheme_AnnotationMixin
   with RawEscapeSchemeRuntimeValuedPropertiesMixin {
 
-  final override lazy val enclosingComponent = Some(defES)
+  final protected override def enclosingComponentDef = Some(defES)
 
   final lazy val referringComponent: Option[SchemaComponent] = Some(defES)
 
@@ -118,7 +118,7 @@
     espev.compile()
     espev
   }
-  
+
   final lazy val escapeSchemeUnparseEv: EscapeSchemeUnparseEv = {
     val esuev = escapeKind match {
       case EscapeKind.EscapeBlock => new EscapeSchemeBlockUnparseEv(escapeBlockStart, escapeBlockEnd, optionEscapeEscapeCharacterEv, optionExtraEscapedCharacters, generateEscapeBlock, runtimeData)
@@ -140,7 +140,7 @@
   // with DefineEscapeScheme_AnnotationMixin
   {
 
-  override lazy val enclosingComponent = Some(pointOfUse)
+  final override protected def enclosingComponentDef = Some(pointOfUse)
 
   /*
    * For diagnostic messages, we need the decl - because that's where the
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLSchemaFile.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLSchemaFile.scala
index 43939cc..cb3fb98 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLSchemaFile.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLSchemaFile.scala
@@ -81,7 +81,7 @@
 
   lazy val schemaSource = schemaSourceArg
 
-  override lazy val enclosingComponent = None
+  final override protected def enclosingComponentDef = None
 
   private var validationDiagnostics_ : Seq[Diagnostic] = Nil
 
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLStatementMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLStatementMixin.scala
index 5750638..74b32a5 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLStatementMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/DFDLStatementMixin.scala
@@ -32,9 +32,12 @@
 
 package edu.illinois.ncsa.daffodil.dsom
 
-import edu.illinois.ncsa.daffodil.exceptions.ThrowsSDE
 import scala.xml.Node
 
+import edu.illinois.ncsa.daffodil.exceptions.ThrowsSDE
+import edu.illinois.ncsa.daffodil.schema.annotation.props.gen.TestKind
+import edu.illinois.ncsa.daffodil.processors.AssertBase
+
 /**
  * The other kind of DFDL annotations are DFDL 'statements'.
  * This trait is everything shared by schema components that can have
@@ -110,4 +113,61 @@
     checkDistinctVariableNames(svs)
   }
 
+  private def getParserExprReferencedElements(s: DFDLStatement,
+    f: ContentValueReferencedElementInfoMixin => Set[DPathElementCompileInfo]) = {
+    s match {
+
+      case a: DFDLAssertionBase if (a.testKind eq TestKind.Expression) => {
+        a.gram match {
+          case ab: AssertBase => f(ab.expr)
+          case _ => ReferencedElementInfos.None
+        }
+      }
+
+      case _ => getUnparserExprReferencedElements(s, f)
+    }
+  }
+
+  private def getUnparserExprReferencedElements(s: DFDLStatement,
+    f: ContentValueReferencedElementInfoMixin => Set[DPathElementCompileInfo]) = {
+    s match {
+      case sv: DFDLSetVariable => {
+        val mdv = sv.defv.maybeDefaultValueExpr
+        if (mdv.isDefined)
+          f(mdv.get)
+        else
+          ReferencedElementInfos.None
+      }
+      case nv: DFDLNewVariableInstance => {
+        // nv.defaultValueExpr.contentReferencedElementInfos
+        ???
+      }
+      case _ => ReferencedElementInfos.None
+    }
+  }
+
+  private def creis(rei: ContentValueReferencedElementInfoMixin) = rei.contentReferencedElementInfos
+  private def vreis(rei: ContentValueReferencedElementInfoMixin) = rei.valueReferencedElementInfos
+
+  private def statementReferencedElementInfos(f: DFDLStatement => Set[DPathElementCompileInfo]) = {
+
+    val stmtSets: Seq[DPathElementCompileInfo] = {
+      val s = statements
+      val sets = s.flatMap(f)
+      sets
+    }
+    stmtSets.toSet
+  }
+
+  final protected lazy val statementContentParserReferencedElementInfos =
+    statementReferencedElementInfos(x => getParserExprReferencedElements(x, creis(_)))
+
+  final protected lazy val statementContentUnparserReferencedElementInfos =
+    statementReferencedElementInfos(x => getUnparserExprReferencedElements(x, creis(_)))
+
+  final protected lazy val statementValueParserReferencedElementInfos =
+    statementReferencedElementInfos(x => getParserExprReferencedElements(x, vreis(_)))
+
+  final protected lazy val statementValueUnparserReferencedElementInfos =
+    statementReferencedElementInfos(x => getUnparserExprReferencedElements(x, vreis(_)))
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementBase.scala
index b6d3d0e..73d2eee 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementBase.scala
@@ -44,7 +44,6 @@
 import edu.illinois.ncsa.daffodil.dpath.NodeInfo
 import edu.illinois.ncsa.daffodil.dpath.NodeInfo.PrimType
 import edu.illinois.ncsa.daffodil.grammar.ElementBaseGrammarMixin
-import edu.illinois.ncsa.daffodil.dpath.WholeExpression
 import edu.illinois.ncsa.daffodil.processors.unparsers.NextElementResolver
 import edu.illinois.ncsa.daffodil.processors.unparsers.SeveralPossibilitiesForNextElement
 import edu.illinois.ncsa.daffodil.equality._
@@ -78,7 +77,6 @@
  */
 abstract class ElementBase(xmlArg: Node, parent: SchemaComponent, position: Int)
   extends Term(xmlArg, parent, position)
-  with AnnotatedMixin
   with Element_AnnotationMixin
   with NillableMixin
   with DFDLStatementMixin
@@ -121,16 +119,71 @@
 
   def isRequired = true // overridden in particle mixin.
 
-  final lazy val notReferencedByExpressions = {
-    val ise = inScopeExpressions
-    val hasThem = ise.exists { _.hasReferenceTo(dpathElementCompileInfo) }
-    !hasThem
+  override final protected def calcContentParserReferencedElementInfos =
+    if (this.inputValueCalcOption.isDefined)
+      ivcCompiledExpression.contentReferencedElementInfos
+    else
+      ReferencedElementInfos.None
+
+  override final protected def calcContentUnparserReferencedElementInfos =
+    if (this.outputValueCalcOption.isDefined)
+      ovcCompiledExpression.contentReferencedElementInfos
+    else
+      ReferencedElementInfos.None
+
+  override final protected def calcValueParserReferencedElementInfos =
+    if (this.inputValueCalcOption.isDefined) {
+      val ivcCE = ivcCompiledExpression
+      val setERs = ivcCE.valueReferencedElementInfos
+      setERs
+    } else
+      ReferencedElementInfos.None
+
+  override final protected def calcValueUnparserReferencedElementInfos =
+    if (this.outputValueCalcOption.isDefined)
+      ovcCompiledExpression.valueReferencedElementInfos
+    else
+      ReferencedElementInfos.None
+
+  final lazy val isReferencedByContentLengthParserExpressions: Boolean =
+    rootElement.get.contentLengthParserReferencedElementInfos.contains(this.dpathElementCompileInfo)
+
+  final lazy val isReferencedByContentLengthUnparserExpressions: Boolean =
+    rootElement.get.contentLengthUnparserReferencedElementInfos.contains(this.dpathElementCompileInfo)
+
+  final lazy val isReferencedByValueLengthParserExpressions: Boolean = {
+    val setElems = rootElement.get.valueLengthParserReferencedElementInfos
+    //    if (this eq rootElement.get)
+    //      println("PARSER these are referenced by valueCalc: " + setElems.toString)
+    val res = setElems.contains(this.dpathElementCompileInfo)
+    res
+  }
+
+  final lazy val isReferencedByValueLengthUnparserExpressions: Boolean = {
+    val setElems = rootElement.get.valueLengthUnparserReferencedElementInfos
+    //    if (this eq rootElement.get)
+    //      println("UNPARSER these are referenced by valueCalc: " + setElems.toString)
+    val isInExprs = setElems.contains(this.dpathElementCompileInfo)
+    val res = isInExprs ||
+      otherwiseShouldCaptureValueRegionLength
+    res
   }
 
   /**
-   * Stream because we don't want to necessarily enumerate all of them
+   * Besides being referenced by the dfdl:valueLength function,
+   * We need the valueLength to be computed for unparser pad/fill, to check
+   * excess length, and for alignmentFills.
+   *
+   * TBD: why for alignment fills? Don't see using it in the code. Try without this?
    */
-  def inScopeExpressions: Stream[WholeExpression] = Stream.empty
+  private lazy val otherwiseShouldCaptureValueRegionLength: Boolean = {
+    val pad = this.shouldAddPadding
+    val fill = this.shouldAddFill
+    val len = this.shouldCheckExcessLength
+    val alg = !this.isKnownToBeAligned // alignment fill uses the value length.
+    val res = pad || fill || len || alg
+    res
+  }
 
   final lazy val simpleType = {
     Assert.usage(isSimpleType)
@@ -155,7 +208,7 @@
       enclosingElement.map { _.dpathElementCompileInfo },
       variableMap,
       namespaces,
-      path,
+      slashPath,
       slotIndexInParent,
       name,
       isArray,
@@ -455,7 +508,7 @@
       //
       // unparser specific items
       //
-      notReferencedByExpressions,
+      false, // !isReferencedByExpressions, // assume it is always to be referenced by expressions
       optTruncateSpecifiedLengthString,
       if (isOutputValueCalc) Some(ovcCompiledExpression) else None)
     newERD
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementDeclMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementDeclMixin.scala
index 6e663c5..5b0f5be 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementDeclMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementDeclMixin.scala
@@ -42,7 +42,7 @@
  * Shared by all element declarations local or global
  */
 trait ElementDeclMixin
-    extends OverlapCheckMixin { self: ElementBase =>
+  extends OverlapCheckMixin { self: ElementBase =>
 
   private def eRefNonDefault: Option[ChainPropProvider] = LV('eRefNonDefault) {
     elementRef.map {
@@ -237,4 +237,5 @@
 
   final override lazy val inputValueCalcOption = findPropertyOption("inputValueCalc")
   final override lazy val outputValueCalcOption = findPropertyOption("outputValueCalc")
+
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementRef.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementRef.scala
index 8999313..439011a 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementRef.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/ElementRef.scala
@@ -52,10 +52,10 @@
  * doesn't.
  */
 final class ElementRef(xmlArg: Node, parent: ModelGroup, position: Int)
-    extends LocalElementBase(xmlArg, parent, position)
-    with ElementReferenceGrammarMixin
-    with HasRefMixin
-    with NamedMixin {
+  extends LocalElementBase(xmlArg, parent, position)
+  with ElementReferenceGrammarMixin
+  with HasRefMixin
+  with NamedMixin {
 
   requiredEvaluations(referencedElement)
 
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GlobalElementDecl.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GlobalElementDecl.scala
index 5731181..aaffcb0 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GlobalElementDecl.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GlobalElementDecl.scala
@@ -43,16 +43,16 @@
  * combination of an ElementRef plus its GlobalElementDecl behaves like a LocalElementDecl.
  */
 final class GlobalElementDecl(xmlArg: Node, schemaDocumentArg: SchemaDocument, override val elementRef: Option[ElementRef])
-    extends LocalElementBase(xmlArg, schemaDocumentArg, 0)
-    with GlobalComponentMixin
-    with ElementDeclMixin
-    with GlobalElementDeclGrammarMixin
-    /*
+  extends LocalElementBase(xmlArg, schemaDocumentArg, 0)
+  with GlobalComponentMixin
+  with ElementDeclMixin
+  with GlobalElementDeclGrammarMixin
+  /*
    * global elements combined with element references referring to them can
    * be multiple occurring (aka arrays) hence, we have to have things
    * that take root and referenced situation into account.
    */
-    with RequiredOptionalMixin {
+  with RequiredOptionalMixin {
 
   override lazy val maxOccurs = elementRef match {
     case Some(er) => er.maxOccurs
@@ -68,7 +68,7 @@
 
   override lazy val isHidden = if (isRoot) false else elementRef.get.isHidden
 
-  override lazy val enclosingComponent = elementRef.flatMap { _.enclosingComponent }
+  final override protected def enclosingComponentDef = elementRef.flatMap { _.enclosingComponent }
 
   override lazy val referringComponent: Option[SchemaComponent] = elementRef
 
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GroupDef.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GroupDef.scala
index 5912353..cfd3a11 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GroupDef.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/GroupDef.scala
@@ -70,7 +70,7 @@
     res
   }
 
-  final override lazy val enclosingComponent = groupRef.enclosingComponent
+  final override protected def enclosingComponentDef = groupRef.enclosingComponent
 
   //
   // Note: Dealing with XML can be fragile. It's easy to forget some of these children
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/InitiatedTerminatedMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/InitiatedTerminatedMixin.scala
index 7292336..0ed7f20 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/InitiatedTerminatedMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/InitiatedTerminatedMixin.scala
@@ -51,14 +51,14 @@
   }
 
   final lazy val hasInitiator = {
-    val hasOne = initiatorParseEv.isKnownNonEmpty
+    val hasOne = initiatorExpr.isKnownNonEmpty
     if (parentSaysInitiatedContent)
       schemaDefinitionUnless(hasOne, "Enclosing group has initiatedContent='yes', but initiator is not defined.")
     hasOne
   }
 
   final lazy val hasTerminator = {
-    terminatorParseEv.isKnownNonEmpty
+    terminatorExpr.isKnownNonEmpty
   }
 
   lazy val initiatorDiscriminator = prod("initiatorDiscriminator", parentSaysInitiatedContent) { InitiatedContent(this) }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/NamedMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/NamedMixin.scala
index 375eb79..099abe5 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/NamedMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/NamedMixin.scala
@@ -2,25 +2,25 @@
  *
  * Developed by: Tresys Technology, LLC
  *               http://www.tresys.com
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  * this software and associated documentation files (the "Software"), to deal with
  * the Software without restriction, including without limitation the rights to
  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  * of the Software, and to permit persons to whom the Software is furnished to do
  * so, subject to the following conditions:
- * 
+ *
  *  1. Redistributions of source code must retain the above copyright notice,
  *     this list of conditions and the following disclaimers.
- * 
+ *
  *  2. Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimers in the
  *     documentation and/or other materials provided with the distribution.
- * 
+ *
  *  3. Neither the names of Tresys Technology, nor the names of its contributors
  *     may be used to endorse or promote products derived from this Software
  *     without specific prior written permission.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -83,7 +83,7 @@
    * which is to go back to their referring component (which will be None only for
    * the root element.
    */
-  override lazy val enclosingComponent = {
+  override protected def enclosingComponentDef = {
     Assert.invariant(context.isInstanceOf[SchemaDocument]) // global things have schema documents as their parents.
     referringComponent
   }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RawCommonRuntimeValuedPropertiesMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RawCommonRuntimeValuedPropertiesMixin.scala
index 50d08dd..e89ee3c 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RawCommonRuntimeValuedPropertiesMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RawCommonRuntimeValuedPropertiesMixin.scala
@@ -76,9 +76,9 @@
   extends PropertyMixin {
 
   // package private because used in unit test
-  private[dsom] final lazy val optionEscapeCharacterRaw = findPropertyOption("escapeCharacter")
+  final lazy val optionEscapeCharacterRaw = findPropertyOption("escapeCharacter")
   private[dsom] final lazy val escapeCharacterRaw = requireProperty(optionEscapeCharacterRaw)
-  protected final lazy val optionEscapeEscapeCharacterRaw = findPropertyOption("escapeEscapeCharacter")
+  final lazy val optionEscapeEscapeCharacterRaw = findPropertyOption("escapeEscapeCharacter")
   protected final lazy val escapeEscapeCharacterRaw = requireProperty(optionEscapeEscapeCharacterRaw)
   protected final lazy val optionEscapeBlockStartRaw = findPropertyOption("escapeBlockStart")
   protected final lazy val escapeBlockStartRaw = requireProperty(optionEscapeBlockStartRaw)
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RealTermMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RealTermMixin.scala
index 741e9e3..f37f0bf 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RealTermMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RealTermMixin.scala
@@ -34,6 +34,40 @@
 
 import edu.illinois.ncsa.daffodil.exceptions.Assert
 
+trait PropertyReferencedElementInfosMixin {
+  protected final type F = ContentValueReferencedElementInfoMixin => Set[DPathElementCompileInfo]
+
+  /**
+   * Convenience method to make gathering up all elements referenced in expressions
+   * easier.
+   */
+  protected final def propExprElts(rawProp: PropertyLookupResult,
+    evArg: => ContentValueReferencedElementInfoMixin,
+    f: F): Set[DPathElementCompileInfo] = {
+    lazy val ev = evArg
+    if (rawProp.isDefined) f(ev) else Set()
+  }
+
+  final protected def creis(rei: ContentValueReferencedElementInfoMixin) = rei.contentReferencedElementInfos
+  final protected def vreis(rei: ContentValueReferencedElementInfoMixin) = rei.valueReferencedElementInfos
+
+  protected def propertyContentReferencedElementInfos: Set[DPathElementCompileInfo]
+  protected def propertyValueReferencedElementInfos: Set[DPathElementCompileInfo]
+
+  protected def statementContentParserReferencedElementInfos: Set[DPathElementCompileInfo]
+  protected def calcContentParserReferencedElementInfos = ReferencedElementInfos.None
+
+  protected def statementContentUnparserReferencedElementInfos: Set[DPathElementCompileInfo]
+  protected def calcContentUnparserReferencedElementInfos = ReferencedElementInfos.None
+
+  protected def statementValueParserReferencedElementInfos: Set[DPathElementCompileInfo]
+  protected def calcValueParserReferencedElementInfos = ReferencedElementInfos.None
+
+  protected def statementValueUnparserReferencedElementInfos: Set[DPathElementCompileInfo]
+  protected def calcValueUnparserReferencedElementInfos = ReferencedElementInfos.None
+
+}
+
 /**
  * A RealTerm is an element or a sequence or a choice. Group references
  * are excluded as they go away and really have no realization.
@@ -185,4 +219,74 @@
     listOfNextTerm
   }.value
 
+  /**
+   * Set of elements referenced from an expression in the scope of this term.
+   *
+   * Specific to certain function call contexts e.g., only elements referenced
+   * by dfdl:valueLength or dfdl:contentLength.
+   *
+   * Separated by parser/unparser since parsers have to derive from
+   * dfdl:inputValueCalc, and must include discriminators and assert test
+   * expressions. Unparsers must derive from dfdl:outputValueCalc and exclude
+   * discriminators and asserts. Both must include setVariable/newVariableInstance,
+   * and property expressions are nearly the same. There are some unparser-specfic
+   * properties that take runtime-valued expressions - dfdl:outputNewLine is
+   * one example.
+   */
+  final lazy val contentLengthParserReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val propRefs = propertyContentReferencedElementInfos
+    val stmtRefs = statementContentParserReferencedElementInfos
+    val calcRefs = calcContentParserReferencedElementInfos
+    val locRefs = propRefs ++ stmtRefs ++ calcRefs
+    val res = realChildren.foldLeft(locRefs) { (s, i) => s.union(i.contentLengthParserReferencedElementInfos) }
+    res
+  }
+
+  /**
+   * Any element referenced from an expression in the scope of this term
+   * is in this set.
+   */
+  final lazy val contentLengthUnparserReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val propRefs = propertyContentReferencedElementInfos
+    val stmtRefs = statementContentUnparserReferencedElementInfos
+    val calcRefs = calcContentUnparserReferencedElementInfos
+    val locRefs = propRefs ++ stmtRefs ++ calcRefs
+    val res = realChildren.foldLeft(locRefs) { (s, i) => s.union(i.contentLengthUnparserReferencedElementInfos) }
+    res
+  }
+
+  /**
+   * Any element referenced from an expression in the scope of this term
+   * is in this set.
+   */
+  final lazy val valueLengthParserReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val propRefs = propertyValueReferencedElementInfos
+    val stmtRefs = statementValueParserReferencedElementInfos
+    val calcRefs = calcValueParserReferencedElementInfos
+    val locRefs = propRefs ++ stmtRefs ++ calcRefs
+    val res = realChildren.foldLeft(locRefs) { (s, i) => s.union(i.valueLengthParserReferencedElementInfos) }
+    res
+  }
+
+  /**
+   * Any element referenced from an expression in the scope of this term
+   * is in this set.
+   */
+  final lazy val valueLengthUnparserReferencedElementInfos: Set[DPathElementCompileInfo] = {
+    val propRefs = propertyValueReferencedElementInfos
+    val stmtRefs = statementValueUnparserReferencedElementInfos
+    val calcRefs = calcValueUnparserReferencedElementInfos
+    val locRefs = propRefs ++ stmtRefs ++ calcRefs
+    val res = realChildren.foldLeft(locRefs) { (s, i) => s.union(i.valueLengthUnparserReferencedElementInfos) }
+    res
+  }
+
+  private lazy val realChildren: Seq[RealTermMixin] = {
+    this match {
+      case mg: ModelGroup => mg.groupMembersNoRefs.asInstanceOf[Seq[RealTermMixin]]
+      case eb: ElementBase if (eb.isComplexType) => Seq(eb.elementComplexType.group)
+      case eb: ElementBase => Seq()
+    }
+  }
+
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RuntimePropertyMixins.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RuntimePropertyMixins.scala
index 3832abe..1e0f3a4 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RuntimePropertyMixins.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/RuntimePropertyMixins.scala
@@ -86,6 +86,7 @@
 
 trait TermRuntimeValuedPropertiesMixin
   extends DFDLBaseTypeMixin
+  with PropertyReferencedElementInfosMixin
   with RawCommonRuntimeValuedPropertiesMixin { decl: Term =>
 
   private lazy val encodingExpr = LV('encoding) {
@@ -153,6 +154,20 @@
       Nope
   }
 
+  private lazy val myPropertyContentReferencedElementInfos =
+    propExprElts(optionEncodingRaw, encodingEv, creis(_)) ++
+      propExprElts(optionOutputNewLineRaw, outputNewLineEv, creis(_))
+
+  override protected def propertyContentReferencedElementInfos =
+    myPropertyContentReferencedElementInfos
+
+  private lazy val myPropertyValueReferencedElementInfos =
+    propExprElts(optionEncodingRaw, encodingEv, vreis(_)) ++
+      propExprElts(optionOutputNewLineRaw, outputNewLineEv, vreis(_))
+
+  override protected def propertyValueReferencedElementInfos =
+    myPropertyValueReferencedElementInfos
+
 }
 
 trait DelimitedRuntimeValuedPropertiesMixin
@@ -166,7 +181,7 @@
     }
   }
 
-  private lazy val initiatorExpr = {
+  final protected lazy val initiatorExpr = {
     val qn = this.qNameForProperty("initiator")
     val typeIfStaticallyKnown = NodeInfo.String
     val typeIfRuntimeKnown = NodeInfo.NonEmptyString
@@ -186,7 +201,7 @@
 
   final def initiatorLoc = (this.prettyName, this.path)
 
-  private lazy val terminatorExpr = LV('terminator) {
+  final protected lazy val terminatorExpr = LV('terminator) {
     val qn = this.qNameForProperty("terminator")
     val typeIfStaticallyKnown = NodeInfo.String
     val typeIfRuntimeKnown = NodeInfo.NonEmptyString
@@ -205,6 +220,14 @@
     ev.compile()
     ev
   }
+
+  private lazy val myPropertyContentReferencedElementInfos =
+    super.propertyContentReferencedElementInfos ++
+      propExprElts(optionInitiatorRaw, initiatorExpr, creis(_)) ++
+      propExprElts(optionTerminatorRaw, terminatorExpr, creis(_))
+
+  override protected def propertyContentReferencedElementInfos =
+    myPropertyContentReferencedElementInfos
 }
 
 trait ElementRuntimeValuedPropertiesMixin
@@ -230,7 +253,7 @@
     ExpressionCompilers.JLong.compile(qn, NodeInfo.Long, lengthRaw)
   }
 
-  private lazy val explicitLengthEv: LengthEv = {
+  private lazy val explicitLengthEv: ExplicitLengthEv = {
     Assert.usage(lengthKind eq LengthKind.Explicit)
     val ev = new ExplicitLengthEv(lengthExpr, erd)
     ev.compile()
@@ -246,7 +269,8 @@
       case (Text, String) => new ImplicitLengthEv(maxLengthLong, erd)
       case (Binary, HexBinary) => new ImplicitLengthEv(maxLengthLong, erd)
       case (Binary, _) => new ImplicitLengthEv(implicitBinaryLengthInBits, erd)
-      case (Text, _) => SDE("Type %s with dfdl:representation='text' cannot have dfdl:lengthKind='implicit'", typeDef.kind.name)
+      case (Text, _) =>
+        SDE("Type %s with dfdl:representation='text' cannot have dfdl:lengthKind='implicit'", typeDef.kind.name)
     }
     ev.compile()
     ev
@@ -265,7 +289,7 @@
   }
 
   final lazy val maybeLengthEv: Maybe[LengthEv] = {
-    if (this.optionLengthRaw.isDefined) One(lengthEv)
+    if (this.optionLengthRaw.isDefined && (lengthKind eq LengthKind.Explicit)) One(lengthEv)
     else None
   }
 
@@ -432,6 +456,52 @@
     else
       Nope
   }
+
+  private def lengthReferencedElements(f: F) =
+    if (maybeLengthEv.isDefined)
+      f(this.explicitLengthEv)
+    else
+      ReferencedElementInfos.None
+
+  private def localElementPropertyReferencedElements(f: F) = {
+    propExprElts(optionByteOrderRaw, byteOrderEv, f) ++
+      lengthReferencedElements(f) ++
+      propExprElts(optionOccursCountRaw, occursCountEv, f) ++
+      propExprElts(optionTextStandardDecimalSeparatorRaw, textStandardDecimalSeparatorEv, f) ++
+      propExprElts(optionTextStandardGroupingSeparatorRaw, textStandardGroupingSeparatorEv, f) ++
+      propExprElts(optionTextStandardExponentRepRaw, textStandardExponentRepEv, f) ++
+      propExprElts(optionBinaryFloatRepRaw, binaryFloatRepEv, f) ++
+      propExprElts(optionTextBooleanTrueRepRaw, textBooleanTrueRepEv, f) ++
+      propExprElts(optionTextBooleanFalseRepRaw, textBooleanFalseRepEv, f) ++
+      propExprElts(optionCalendarLanguageRaw, calendarLanguage, f) ++
+      (
+        if (optionEscapeScheme.isDefined) {
+          val es: DFDLEscapeScheme = optionEscapeScheme.get
+          val ee =
+            if (es.optionEscapeEscapeCharacterEv.isDefined)
+              f(es.optionEscapeEscapeCharacterEv.get)
+            else
+              ReferencedElementInfos.None
+          ee ++
+            propExprElts(es.optionEscapeCharacterRaw, es.escapeCharacterEv, f)
+        } else {
+          ReferencedElementInfos.None
+        })
+  }
+
+  private lazy val myPropertyContentReferencedElementInfos =
+    super.propertyContentReferencedElementInfos ++
+      localElementPropertyReferencedElements(creis(_))
+
+  final override protected def propertyContentReferencedElementInfos =
+    myPropertyContentReferencedElementInfos
+
+  private lazy val myPropertyValueReferencedElementInfos =
+    super.propertyValueReferencedElementInfos ++
+      localElementPropertyReferencedElements(vreis(_))
+
+  final override protected def propertyValueReferencedElementInfos =
+    myPropertyValueReferencedElementInfos
 }
 
 trait SequenceRuntimeValuedPropertiesMixin
@@ -458,6 +528,21 @@
   }
 
   final def separatorLoc = (this.prettyName, this.path)
+
+  private lazy val myPropertyContentReferencedElementInfos =
+    super.propertyContentReferencedElementInfos ++
+      propExprElts(optionSeparatorRaw, separatorExpr, creis(_))
+
+  final override protected def propertyContentReferencedElementInfos =
+    myPropertyContentReferencedElementInfos
+
+  private lazy val myPropertyValueReferencedElementInfos =
+    super.propertyContentReferencedElementInfos ++
+      propExprElts(optionSeparatorRaw, separatorExpr, vreis(_))
+
+  final override protected def propertyValueReferencedElementInfos =
+    myPropertyValueReferencedElementInfos
+
 }
 
 trait SimpleTypeRuntimeValuedPropertiesMixin
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponent.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponent.scala
index 976362f..b3c347e 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponent.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponent.scala
@@ -70,6 +70,11 @@
 
   val context: SchemaComponent = parent
 
+  override protected def enclosingComponentDef =
+    super.enclosingComponentDef.asInstanceOf[Option[SchemaComponent]]
+
+  override final lazy val enclosingComponent = enclosingComponentDef
+
   /**
    * Annotations can contain expressions, so we need to be able to compile them.
    *
@@ -175,11 +180,6 @@
     }
   }.value
 
-  override lazy val enclosingComponent = LV('enclosingComponent) {
-    val res = enclosingComponentDef.asInstanceOf[Option[SchemaComponent]]
-    res
-  }.value
-
   /**
    * All schema components except the root have an enclosing element.
    */
@@ -193,6 +193,16 @@
     ee
   }.value
 
+  final lazy val rootElement: Option[GlobalElementDecl] = {
+    enclosingElement match {
+      case Some(e) => e.rootElement
+      case None => this match {
+        case eb: ElementBase => Some(eb.asInstanceOf[GlobalElementDecl])
+        case _ => None
+      }
+    }
+  }
+
   final lazy val enclosingTerm: Option[Term] = {
     enclosingComponent match {
       case None => None
@@ -211,6 +221,18 @@
     p
   }
 
+  /**
+   * Elements only e.g., /foo/ex:bar
+   */
+  final lazy val slashPath: String = {
+    val thisOne = "/" + prettyName
+    val encElem = enclosingElement
+    if (encElem.isDefined)
+      encElem.get.slashPath + thisOne
+    else
+      thisOne
+  }
+
   override def toString = prettyName
 
   /**
@@ -282,7 +304,7 @@
 
   override def targetNamespace: NS = namespace
 
-  override lazy val enclosingComponent = None
+  final override protected def enclosingComponentDef = None
   override lazy val schemaDocument: SchemaDocument = Assert.usageError("schemaDocument should not be called on Schema")
 
   override lazy val schemaSet = schemaSetArg
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponentBase.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponentBase.scala
index ccbc19b..099532b 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponentBase.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaComponentBase.scala
@@ -45,11 +45,11 @@
    *
    * Concrete here only for unit tests that create instances.
    */
-  final def enclosingComponentDef =
+  protected def enclosingComponentDef =
     if (parent != null) Some(parent) else None
 
-  lazy val enclosingComponent = enclosingComponentDef
-
+  def enclosingComponent : Option[SchemaComponentBase]
+ 
   def isHidden = false
 
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaDocument.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaDocument.scala
index 4e3d757..51ca2ff 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaDocument.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaDocument.scala
@@ -64,7 +64,7 @@
  */
 trait SchemaDocumentMixin { self: SchemaComponent =>
 
-  final override lazy val enclosingComponent: Option[SchemaComponent] = None
+  protected final override def enclosingComponentDef: Option[SchemaComponent] = None
 
 }
 
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaSet.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaSet.scala
index d597d89..ec1c70e 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaSet.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/SchemaSet.scala
@@ -93,7 +93,7 @@
 
   override lazy val schemaSet = this
   // These things are needed to satisfy the contract of being a schema component.
-  override lazy val enclosingComponent = None
+  final override protected def enclosingComponentDef = None
   override lazy val schemaDocument = Assert.usageError("schemaDocument should not be called on SchemaSet")
 
   override lazy val lineAttribute: Option[String] = None
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/Term.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/Term.scala
index a41b97a..ec726b1 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/Term.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/dsom/Term.scala
@@ -47,13 +47,13 @@
 
 // A term is content of a group
 abstract class Term(xmlArg: Node, parentArg: SchemaComponent, val position: Int)
-    extends AnnotatedSchemaComponent(xmlArg, parentArg)
-    with TermRuntimeValuedPropertiesMixin
-    with LocalComponentMixin
-    with TermGrammarMixin
-    with DelimitedRuntimeValuedPropertiesMixin
-    with InitiatedTerminatedMixin
-    with TermEncodingMixin {
+  extends AnnotatedSchemaComponent(xmlArg, parentArg)
+  with TermRuntimeValuedPropertiesMixin
+  with LocalComponentMixin
+  with TermGrammarMixin
+  with DelimitedRuntimeValuedPropertiesMixin
+  with InitiatedTerminatedMixin
+  with TermEncodingMixin {
 
   def optIgnoreCase: Option[YesNo] = {
     val ic = cachePropertyOption("ignoreCase")
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/AlignedMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/AlignedMixin.scala
index f3b05f9..4108837 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/AlignedMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/AlignedMixin.scala
@@ -58,6 +58,18 @@
     else false
   }.value
 
+  final lazy val isKnownToBeTextAligned: Boolean = {
+    if (self.encodingInfo.isKnownEncoding &&
+      self.encodingInfo.knownEncodingAlignmentInBits == 1)
+      true
+    else if (isKnownToBePrecededByAllByteLengthItems)
+      true
+    else if (this.rootElement.get.isScannable)
+      true
+    else
+      false
+  }
+
   // TODO: deal with case of a bit field that is not a multiple of bytes wide
   // but has a terminator which is text and so has mandatory alignment.
   //  /**
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/ElementBaseGrammarMixin.scala
index 3fcc2be..7344f8c 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/ElementBaseGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/ElementBaseGrammarMixin.scala
@@ -75,27 +75,245 @@
     }
   }
 
+  protected lazy val isDelimitedPrefixedPattern = {
+    import LengthKind._
+    lengthKind match {
+      case Delimited => true // don't test for hasDelimiters because it might not be our delimiter, but a surrounding group's separator, or it's terminator, etc.
+      case Pattern => true
+      case Prefixed => true
+      case _ => false
+    }
+  }
+
   /**
    * true if padding will be inserted for this delimited element when unparsing.
    */
   protected lazy val isDelimitedPrefixedPatternWithPadding = {
-    import LengthKind._
-    val isRightLengthKind =
-      lengthKind match {
-        case Delimited => true // don't test for hasDelimiters because it might not be our delimiter, but a surrounding group's separator, or it's terminator, etc.
-        case Pattern => true
-        case Prefixed => true
-        case _ => false
-      }
-    (isRightLengthKind &&
+    (isDelimitedPrefixedPattern &&
       (impliedRepresentation eq Representation.Text) &&
       (justificationPad ne TextJustificationType.None) &&
       minLen > 0)
   }
 
-  lazy val shouldAddPadding =
-    maybeUnparseTargetLengthInBitsEv.isDefined ||
-      isDelimitedPrefixedPatternWithPadding
+  /**
+   * Quite tricky when we add padding or fill
+   *
+   * For complex types, there has to be a length defined. That's it.
+   *
+   * For simple types, we need the fill region processors
+   * to detect excess length
+   */
+  final lazy val shouldAddPadding = {
+    val res =
+      if (isComplexType &&
+        (this.maybeLengthEv.isDefined) &&
+        (lengthUnits eq LengthUnits.Characters))
+        maybeUnparseTargetLengthInBitsEv.isDefined // "pad" complex types.
+      else if (isDelimitedPrefixedPatternWithPadding)
+        true // simple type for unparse that needs to be padded.
+      else
+        // simple type, specified length.
+        (maybeUnparseTargetLengthInBitsEv.isDefined &&
+          (justificationPad ne TextJustificationType.None)) // None if not text.
+    //    if (res)
+    //      println("%s should add padding.".format(this.prettyName))
+    //    else
+    //      println("%s NOT adding padding.".format(this.prettyName))
+    res
+  }
+
+  /**
+   * We add fill to complex types of specified length so long as length units
+   * are bytes/bits. If characters then "pad" puts the characters on.
+   *
+   * We also add it to text elements of variable specified length again, unless
+   * length units are in characters.
+   */
+  final lazy val shouldAddFill = {
+    val res =
+      (isComplexType &&
+        isSpecifiedLengthForUnparsing &&
+        (lengthUnits ne LengthUnits.Characters)) ||
+        (isSimpleType &&
+          isSpecifiedLengthForUnparsing &&
+          couldBeVariableLengthInfoset &&
+          (lengthUnits ne LengthUnits.Characters))
+    //    if (res)
+    //      println("%s should add fill.".format(this.prettyName))
+    //    else
+    //      println("%s NOT adding fill.".format(this.prettyName))
+    res
+  }
+
+  //  /**
+  //   * Means the representation could have varying sizes.
+  //   *
+  //   * Does not mean the infoset element might be bigger or smaller and
+  //   * might get truncated or padded to fit a fixed size representation.
+  //   *
+  //   * This is about whether the box we're fitting it into is fixed or varying size.
+  //   */
+  //  final protected lazy val isVariableLengthRep: Boolean = {
+  //    isDelimitedPrefixedPattern ||
+  //      ((lengthKind eq LengthKind.Explicit) &&
+  //        !lengthEv.optConstant.isDefined)
+  //        //
+  //        // TODO: do we have to consider utf-8 situation for strings when
+  //        // even though the length is constant, because it's utf-8
+  //        // the length units are characters but we don't know
+  //        // how many bytes without knowing what characters are?
+  //        //
+  //        // This requires an Evaluatable, since it depends on charset.
+  //        //
+  //        // Also, whether we want this to be true/false depends on
+  //        // context. If the context is a complex type with lengthUnits characters
+  //        // then we're ok with utf-8 fixed number of characters. We're not
+  //        // ok if the complex type has length its bytes, but contains an
+  //        // element with length units bytes and charset utf-8.
+  //        //
+  //  }
+
+  /**
+   * Means the specified length must, necessarily, be big enough to hold the representation
+   * so long as the value in the infoset is legal for the type.
+   *
+   * This does not include numeric range checking. So for example if you
+   * have an xs:unsignedInt but length is 3 bits, this will be true even though an
+   * integer value of greater than 7 cannot fit.
+   *
+   * Another way to think of this is that legal infoset values will have fixed
+   * length representations.
+   *
+   * This is a conservative analysis, meaning if true the property definitely
+   * holds, but if false it may mean we just couldn't tell if it holds or not.
+   *
+   * If this is true, then we never need to check how many bits were written when
+   * unparsing, because we know a legal value has to fit. If the value is illegal
+   * then we'll get an unparse error anyway.
+   *
+   * If this is false, then it's possible that the value, even a legal value,
+   * might not fit if the length is specified. We're unable to prove that all
+   * legal values WILL fit.
+   *
+   * A critical case is that fixed length binary integers should always
+   * return true here so that we're not doing excess length checks on them
+   * Or computing their value length unnecessarily.
+   */
+  final protected lazy val mustBeFixedLengthInfoset = {
+    (isSimpleType &&
+      (impliedRepresentation eq Representation.Binary) &&
+      (primType ne PrimType.HexBinary) &&
+      {
+        import NodeInfo._
+        primType match {
+          case Float => true
+          case Double => true;
+          case n: Numeric.Kind =>
+            binaryNumberRep eq BinaryNumberRep.Binary
+          case _ => true
+        }
+      } &&
+      ((lengthKind eq LengthKind.Implicit) ||
+        ((lengthKind eq LengthKind.Explicit) &&
+          lengthEv.optConstant.isDefined)) // TODO: consider if delimiters matter, alignment, nil values,.... Are we excluding
+          // that stuff here? For example, if the element is nillable, but
+          // if isNilled, the representation will still be exactly the same
+          // length, then we'd like this to be true.
+          ) ||
+          (
+            // a fixed-length textual number, where a legal value
+            // (or nil value) must by definition be smaller than the
+            // fixed length. E.g., since the largest unsignedByte value
+            // is 256, and with textNumberPattern="###" the max width is 3
+            // then so long as the fixed length is 3 or greater we know
+            // it's going to fit.
+            //
+            // Furthermore, if it is nillable, and the nilValue is "nil", which
+            // is also length 3, then it's going to fit.
+            //
+            // Also matters that if the textNumberPattern can output fewer
+            // characters than the fixed width, then padding must be enabled and a
+            // pad char specified, and that the padChar is the same width as
+            // a digit. (similarly if the nilValue was "-" we need to pad that too)
+            //
+            // This also assumes that in every charset encoding the digit
+            // characters are always the same width so the whole utf-8
+            // variable-width encoding crud doesn't apply.
+            //
+            // However, textNumberPattern
+            // matters, because sometimes the lengths of positive and negative
+            // numbers can differ. So the fixed length has to be big enough
+            // for the largest possible textNumber matching the pattern.
+            //
+            false // TODO: implement this
+            ) ||
+            (isComplexType && !isNillable &&
+              (
+                //
+                // recursively, the complex type can contain only isFixedLengthInfoset items
+                // but in addition, no delimiter can be varying width - so there can only be one
+                // delimiter value for each of these, nor can there be any variable-width
+                // alignment regions.
+                //
+                false // TODO: implement this
+                ))
+  }
+
+  /**
+   * Means the infoset element could have varying length.
+   *
+   * And that means if there is a specified length box to fit it into
+   * that we have to check if it is too big/small for the box.
+   *
+   * So that means hexBinary, or representation text (for simple types)
+   * or any complex type unless everything in it is fixedLengthInfoset.
+   *
+   * So for example, a complex type containing only fixed length binary
+   * integers is itself fixed length.
+   */
+  final protected lazy val couldBeVariableLengthInfoset: Boolean = {
+    !mustBeFixedLengthInfoset
+  }
+
+  /**
+   * Only strings can be truncated, only if they are specified length,
+   * and only if truncateSpecifiedLengthString is 'yes'.
+   *
+   * Note that specified length might mean fixed length or variable (but specified)
+   * length.
+   */
+  final protected lazy val isTruncatable = {
+    isSimpleType &&
+      (primType eq PrimType.String) &&
+      (truncateSpecifiedLengthString eq YesNo.Yes) &&
+      isSpecifiedLengthForUnparsing
+  }
+
+  /**
+   * Fixed length, or variable length with explicit length expression.
+   */
+  final protected lazy val isSpecifiedLengthForUnparsing: Boolean = {
+    (isSimpleType && (
+      (lengthKind eq LengthKind.Explicit) ||
+      (lengthKind eq LengthKind.Implicit))) ||
+      (isComplexType &&
+        (lengthKind eq LengthKind.Explicit))
+  }
+
+  /**
+   * Check for excess length if it's variable length and we cannot truncate it.
+   */
+  final lazy val shouldCheckExcessLength = {
+    val res =
+      couldBeVariableLengthInfoset &&
+        !isTruncatable &&
+        isSpecifiedLengthForUnparsing
+    //    if (res)
+    //      println("%s should check excess length.".format(this.prettyName))
+    //    else
+    //      println("%s NOT checking excess length.".format(this.prettyName))
+    res
+  }
 
   private lazy val rightFill = new RightFill(context)
 
@@ -734,13 +952,17 @@
   //
   protected final def enclosedElementNonDefault = enclosedElement
 
+  private lazy val inputValueCalcPrim = InputValueCalc(self, inputValueCalcOption)
+
+  protected final def ivcCompiledExpression = inputValueCalcPrim.expr
+
   private lazy val inputValueCalcElement = prod("inputValueCalcElement",
     isSimpleType && inputValueCalcOption.isInstanceOf[Found]) {
       // No framing surrounding inputValueCalc elements.
       // Note that we need these elements even when unparsing, because they appear in the infoset
       // as regular elements (most times), and so we have to have an unparser that consumes the corresponding events.
       new ElementParseAndUnspecifiedLength(this, dfdlScopeBegin,
-        InputValueCalc(self, inputValueCalcOption), dfdlScopeEnd)
+        inputValueCalcPrim, dfdlScopeEnd)
     }
 
   protected final lazy val ovcCompiledExpression = { // ovcValueCalcObject.expr
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/LocalElementGrammarMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/LocalElementGrammarMixin.scala
index 00d01bc..8cf51a2 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/LocalElementGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/LocalElementGrammarMixin.scala
@@ -50,9 +50,9 @@
 
   private lazy val notStopValue = prod("notStopValue", hasStopValue) { NotStopValue(this) }
 
-  private lazy val separatedEmpty = prod("separatedEmpty", 
-      emptyIsAnObservableConcept && isRecurring) {
-    separatedForArrayPosition(empty)
+  private lazy val separatedEmpty = prod("separatedEmpty",
+    emptyIsAnObservableConcept && isRecurring) {
+      separatedForArrayPosition(empty)
     }
 
   private lazy val separatedRecurringDefaultable = prod("separatedRecurringDefaultable", !isScalar) {
@@ -67,9 +67,9 @@
 
   private lazy val recurrance = prod("recurrance", !isScalar) {
     if (isOptional) {
-      OptionalCombinator(this, arrayContents) ~ FinalUnusedRegion(this)
+      OptionalCombinator(this, arrayContents)
     } else {
-      ArrayCombinator(this, arrayContents) ~ FinalUnusedRegion(this)
+      ArrayCombinator(this, arrayContents)
     }
   }
 
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/TermGrammarMixin.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/TermGrammarMixin.scala
index d9bd18d..d990a4d 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/TermGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/grammar/TermGrammarMixin.scala
@@ -42,9 +42,9 @@
 /////////////////////////////////////////////////////////////////
 
 trait TermGrammarMixin
-    extends AlignedMixin
-    with BitOrderMixin
-    with EncodingChangeMixin { self: Term =>
+  extends AlignedMixin
+  with BitOrderMixin
+  with EncodingChangeMixin { self: Term =>
 
   override protected final def grammarContext = this
 
@@ -200,7 +200,16 @@
   /**
    * Mandatory text alignment for delimiters
    */
-  protected lazy val delimMTA = prod("delimMTA", hasDelimiters) {
-    mtaBase
-  }
+  protected lazy val delimMTA = prod("delimMTA",
+    {
+      //      if (!hasDelimiters) {
+      //        println("Removing MTA for delimiters of " + this.prettyName)
+      //      } else {
+      //        println("MTA region inserted for " + this.prettyName)
+      //      }
+      hasDelimiters
+    }) {
+      mtaBase
+    }
+
 }
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator.scala
index c5f4430..bbfec08 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator.scala
@@ -142,67 +142,11 @@
     }
   }
 
-  //  private lazy val specifiedLengthUnparser: Unparser = {
-  //    context.typeDef.kind match {
-  //      case NodeInfo.Complex => complexSpecifiedLengthUnparser
-  //      case NodeInfo.HexBinary => hexBinarySpecifiedLengthUnparser
-  //      case st: NodeInfo.AnySimpleType.Kind if context.impliedRepresentation _eq_ Representation.Text =>
-  //        simpleTextSpecifiedLengthUnparser
-  //      case st: NodeInfo.AnySimpleType.Kind if context.impliedRepresentation _eq_ Representation.Binary =>
-  //        simpleBinarySpecifiedLengthUnparser
-  //      case k => Assert.invariantFailed("type not accepted: " + k + " with representation " + context.impliedRepresentation + " with lengthKind " + context.lengthKind)
-  //    }
-  //  }
-
-  //  private def maybeUnp(unp: Gram): Maybe[Unparser] = {
-  //    if (unp.isEmpty) Nope
-  //    else One(unp.unparser)
-  //  }
-
-  //  private lazy val complexSpecifiedLengthUnparser: Unparser = {
-  //    val elementUnused = new ElementUnused(context)
-  //    new ComplexElementSpecifiedLengthUnparser(context.erd,
-  //      context.unparseTargetLengthInBitsEv,
-  //      eUnparser, maybeUnp(elementUnused))
-  //  }
-  //
-  //  private lazy val hexBinarySpecifiedLengthUnparser: Unparser = {
-  //    val rightFill = new RightFill(context)
-  //    new HexBinarySpecifiedLengthUnparser(context.erd,
-  //      context.unparseTargetLengthInBitsEv,
-  //      eUnparser, maybeUnp(rightFill))
-  //  }
-  //
-  //  private lazy val simpleBinarySpecifiedLengthUnparser: Unparser = {
-  //    new SimpleBinarySpecifiedLengthUnparser(context.erd,
-  //      context.unparseTargetLengthInBitsEv,
-  //      eUnparser)
-  //  }
-  //
-  //  private lazy val simpleTextSpecifiedLengthUnparser: Unparser = {
-  //    val (leftPadding, rightPadding) = {
-  //      if (unparsingPadChar.isEmpty) (EmptyGram, EmptyGram)
-  //      else {
-  //        import TextJustificationType._
-  //        this.justificationPad match {
-  //          case None => (EmptyGram, EmptyGram)
-  //          case Left => (EmptyGram, OnlyPadding(context))
-  //          case Right => (OnlyPadding(context), EmptyGram)
-  //          case Center => (LeftCenteredPadding(context), RightCenteredPadding(context))
-  //        }
-  //      }
-  //    }
-  //    val rightFill = new RightFill(context)
-  //    new SimpleTextSpecifiedLengthUnparser(context.erd,
-  //      context.unparseTargetLengthInBitsEv,
-  //      maybeUnp(leftPadding), eUnparser,
-  //      maybeUnp(rightPadding), maybeUnp(rightFill))
-  //  }
-
 }
 
 case class ElementUnused(ctxt: ElementBase)
-  extends Terminal(ctxt, ctxt.maybeUnparseTargetLengthInBitsEv.isDefined) {
+  extends Terminal(ctxt, ctxt.shouldAddFill ||
+    ctxt.shouldCheckExcessLength) {
   override def parser = new NadaParser(ctxt.erd)
 
   override lazy val unparser: Unparser = new ElementUnusedUnparser(ctxt.erd,
@@ -219,13 +163,16 @@
 
   override def parser = new NadaParser(ctxt.erd)
 
-  override lazy val unparser: Unparser =
+  override lazy val unparser: Unparser = {
+    Assert.invariant(ctxt.maybeUnparseMinOrTargetLengthInBitsEv.isDefined)
+    val mmtlev = ctxt.maybeUnparseMinOrTargetLengthInBitsEv.get
     new OnlyPaddingUnparser(ctxt.erd,
-      ctxt.maybeUnparseMinOrTargetLengthInBitsEv.get,
+      mmtlev,
       ctxt.maybeLengthEv,
       ctxt.maybeCharsetEv,
       ctxt.maybeLiteralNilEv,
       unparsingPadChar)
+  }
 }
 
 case class NilLiteralCharacter(ctxt: ElementBase)
@@ -274,7 +221,8 @@
 }
 
 case class RightFill(ctxt: ElementBase)
-  extends Terminal(ctxt, ctxt.maybeUnparseTargetLengthInBitsEv.isDefined)
+  extends Terminal(ctxt, ctxt.shouldAddFill ||
+    ctxt.shouldCheckExcessLength)
   with Padded {
   override def parser = new NadaParser(ctxt.erd)
 
@@ -297,58 +245,86 @@
 
 case class CaptureContentLengthStart(ctxt: ElementBase)
   extends Terminal(ctxt, true) {
-  override def parser = new CaptureStartOfContentLengthParser(ctxt.erd)
+  override def parser =
+    if (ctxt.isReferencedByContentLengthParserExpressions)
+      new CaptureStartOfContentLengthParser(ctxt.erd)
+    else
+      new NadaParser(ctxt.erd)
 
   override lazy val unparser: Unparser =
-    new CaptureStartOfContentLengthUnparser(ctxt.erd)
+    if (ctxt.isReferencedByContentLengthUnparserExpressions)
+      new CaptureStartOfContentLengthUnparser(ctxt.erd)
+    else
+      new NadaUnparser(ctxt.erd)
 }
 
 case class CaptureContentLengthEnd(ctxt: ElementBase)
   extends Terminal(ctxt, true) {
-  override def parser = new CaptureEndOfContentLengthParser(ctxt.erd)
+  override def parser =
+    if (ctxt.isReferencedByContentLengthParserExpressions)
+      new CaptureEndOfContentLengthParser(ctxt.erd)
+    else
+      new NadaParser(ctxt.erd)
 
   override lazy val unparser: Unparser =
-    new CaptureEndOfContentLengthUnparser(ctxt.erd)
+    if (ctxt.isReferencedByContentLengthUnparserExpressions)
+      new CaptureEndOfContentLengthUnparser(ctxt.erd)
+    else
+      new NadaUnparser(ctxt.erd)
 }
 
 case class CaptureValueLengthStart(ctxt: ElementBase)
   extends Terminal(ctxt, true) {
-  override def parser = {
-    // For simple elements with text representation, valueLength is captured in
-    // individual parsers since they handle removing delimiters and padding.
-    //
-    // For complex elements with specified length, valueLength is captured in
-    // the specified length parsers, since they handle skipping unused element
-    // regions.
-    //
-    // For all other elements, we can just use the Capture*ValueLength parsers.
-    if ((ctxt.isSimpleType && ctxt.impliedRepresentation == Representation.Text) ||
-      (ctxt.isComplexType && ctxt.lengthKind != LengthKind.Implicit)) new NadaParser(ctxt.erd)
-    else new CaptureStartOfValueLengthParser(ctxt.erd)
-  }
+  override def parser =
+    if (ctxt.isReferencedByValueLengthParserExpressions) {
+      // For simple elements with text representation, valueLength is captured in
+      // individual parsers since they handle removing delimiters and padding.
+      //
+      // For complex elements with specified length, valueLength is captured in
+      // the specified length parsers, since they handle skipping unused element
+      // regions.
+      //
+      // For all other elements, we can just use the Capture*ValueLength parsers.
+      if ((ctxt.isSimpleType && ctxt.impliedRepresentation == Representation.Text) ||
+        (ctxt.isComplexType && ctxt.lengthKind != LengthKind.Implicit))
+        new NadaParser(ctxt.erd)
+      else
+        new CaptureStartOfValueLengthParser(ctxt.erd)
+    } else
+      new NadaParser(ctxt.erd)
 
   override lazy val unparser: Unparser =
-    new CaptureStartOfValueLengthUnparser(ctxt.erd)
+    if (ctxt.isReferencedByValueLengthUnparserExpressions) {
+      new CaptureStartOfValueLengthUnparser(ctxt.erd)
+    } else
+      new NadaUnparser(ctxt.erd)
 }
 
 case class CaptureValueLengthEnd(ctxt: ElementBase)
   extends Terminal(ctxt, true) {
-  override def parser = {
-    // For simple elements with text representation, valueLength is captured in
-    // individual parsers since they handle removing delimiters and padding.
-    //
-    // For complex elements with specified length, valueLength is captured in
-    // the specified length parsers, since they handle skipping unused element
-    // regions.
-    //
-    // For all other elements, we can just use the Capture*ValueLength parsers.
-    if ((ctxt.isSimpleType && ctxt.impliedRepresentation == Representation.Text) ||
-      (ctxt.isComplexType && ctxt.lengthKind != LengthKind.Implicit)) new NadaParser(ctxt.erd)
-    else new CaptureEndOfValueLengthParser(ctxt.erd)
-  }
+  override def parser =
+    if (ctxt.isReferencedByValueLengthParserExpressions) {
+      // For simple elements with text representation, valueLength is captured in
+      // individual parsers since they handle removing delimiters and padding.
+      //
+      // For complex elements with specified length, valueLength is captured in
+      // the specified length parsers, since they handle skipping unused element
+      // regions.
+      //
+      // For all other elements, we can just use the Capture*ValueLength parsers.
+      if ((ctxt.isSimpleType && ctxt.impliedRepresentation == Representation.Text) ||
+        (ctxt.isComplexType && ctxt.lengthKind != LengthKind.Implicit))
+        new NadaParser(ctxt.erd)
+      else
+        new CaptureEndOfValueLengthParser(ctxt.erd)
+    } else
+      new NadaParser(ctxt.erd)
 
   override lazy val unparser: Unparser =
-    new CaptureEndOfValueLengthUnparser(ctxt.erd)
+    if (ctxt.isReferencedByValueLengthUnparserExpressions) {
+      new CaptureEndOfValueLengthUnparser(ctxt.erd)
+    } else
+      new NadaUnparser(ctxt.erd)
 }
 
 /*
diff --git a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/PrimitivesFraming.scala b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/PrimitivesFraming.scala
index 1fcac2c..6754a91 100644
--- a/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/PrimitivesFraming.scala
+++ b/daffodil-core/src/main/scala/edu/illinois/ncsa/daffodil/processors/PrimitivesFraming.scala
@@ -80,20 +80,12 @@
 
   private val alignment = e.alignmentValueInBits
 
-  //  def isAligned(currBitPos: Long): Boolean = {
-  //    if (alignment == 0 || currBitPos == 0) return true
-  //    if ((currBitPos - alignment) < 0) return false
-  //    if ((currBitPos % alignment) == 0) return true
-  //    return false
-  //  }
-
   lazy val parser: Parser = new AlignmentFillParser(alignment, e.runtimeData)
   lazy val unparser: Unparser = new AlignmentFillUnparser(alignment, e.runtimeData, e.fillByteEv)
 }
 
-case class FinalUnusedRegion(e: ElementBase) extends UnimplementedPrimitive(e, false)
-
-case class MandatoryTextAlignment(e: Term, alignmentInBits: Int) extends Terminal(e, alignmentInBits > 1) {
+case class MandatoryTextAlignment(e: Term, alignmentInBits: Int) extends Terminal(e,
+  !e.isKnownToBeTextAligned) {
   Assert.invariant(alignmentInBits > 0)
 
   lazy val parser: Parser = new MandatoryTextAlignmentParser(alignmentInBits, e.runtimeData)
diff --git a/daffodil-core/src/test/scala/edu/illinois/ncsa/daffodil/schema/annotation/props/TestPropertyRuntime.scala b/daffodil-core/src/test/scala/edu/illinois/ncsa/daffodil/schema/annotation/props/TestPropertyRuntime.scala
index 1f65902..ede4af9 100644
--- a/daffodil-core/src/test/scala/edu/illinois/ncsa/daffodil/schema/annotation/props/TestPropertyRuntime.scala
+++ b/daffodil-core/src/test/scala/edu/illinois/ncsa/daffodil/schema/annotation/props/TestPropertyRuntime.scala
@@ -81,8 +81,11 @@
   class HasMixin extends {
     override val xml = <foo/>
   } with SchemaComponentBase(<dummy/>, null)
-      with TheExamplePropMixin
-      with LookupLocation {
+    with TheExamplePropMixin
+    with LookupLocation {
+
+    final override def enclosingComponent: Option[SchemaComponentBase] = None
+
     // Members declared in edu.illinois.ncsa.daffodil.api.LocationInSchemaFile
     def columnDescription: String = ???
     def fileDescription: String = ???
@@ -125,7 +128,7 @@
 }
 
 trait TheExamplePropMixin
-    extends PropertyMixin with ThrowsSDE { self: OOLAGHost =>
+  extends PropertyMixin with ThrowsSDE { self: OOLAGHost =>
 
   def SDE(id: String, args: Any*): Nothing = {
     throw new Exception(id.toString + args)
diff --git a/daffodil-examples/src/test/scala/edu/illinois/ncsa/daffodil/pcap/TestPCAP.scala b/daffodil-examples/src/test/scala/edu/illinois/ncsa/daffodil/pcap/TestPCAP.scala
index 737a266..efe197b 100644
--- a/daffodil-examples/src/test/scala/edu/illinois/ncsa/daffodil/pcap/TestPCAP.scala
+++ b/daffodil-examples/src/test/scala/edu/illinois/ncsa/daffodil/pcap/TestPCAP.scala
@@ -34,18 +34,25 @@
 
 import org.junit.Test
 import edu.illinois.ncsa.daffodil.tdml.Runner
+import org.junit.AfterClass
+
+object TestPCAP {
+  lazy val runner = Runner("/edu/illinois/ncsa/daffodil/pcap/", "pcap.tdml")
+
+  @AfterClass def shutDown {
+    runner.reset
+  }
+}
 
 class TestPCAP {
 
-  lazy val runner = Runner("/edu/illinois/ncsa/daffodil/pcap/", "pcap.tdml")
+  import TestPCAP._
 
-  @Test def test_pcap_test_dns() = // Debugger.withDebugger
-    { runner.runOneTest("pcap_test_dns") }
+  @Test def test_pcap_test_dns() = { runner.runOneTest("pcap_test_dns") }
   @Test def test_pcap_test_http_ipv6() = { runner.runOneTest("pcap_test_http_ipv6") }
   @Test def test_pcap_test_icmp() { runner.runOneTest("pcap_test_icmp") }
   @Test def test_pcap_test_tcp_ecn() { runner.runOneTest("pcap_test_tcp_ecn") }
 
-  // DFDL-1561
   @Test def test_pcap_test_icmp_unparse1() { runner.runOneTest("pcap_test_icmp_unparse1") }
 
 }
diff --git a/daffodil-io/src/main/scala/edu/illinois/ncsa/daffodil/io/DirectOrBufferedDataOutputStream.scala b/daffodil-io/src/main/scala/edu/illinois/ncsa/daffodil/io/DirectOrBufferedDataOutputStream.scala
index 1524fa6..64c60ef 100644
--- a/daffodil-io/src/main/scala/edu/illinois/ncsa/daffodil/io/DirectOrBufferedDataOutputStream.scala
+++ b/daffodil-io/src/main/scala/edu/illinois/ncsa/daffodil/io/DirectOrBufferedDataOutputStream.scala
@@ -357,7 +357,9 @@
    * information when setFinished occurs, which is, after all, the time when we
    * can push such info forward.
    *
-   * However, see setFinished comment that nothing is doing this push forward.
+   * However, see setFinished comment. Where we setFinished and there is a following
+   * DOS we reach forward and ask that for its maybeAbsBitPos0b, which pulls the information
+   * forward by one DOS in the chain. So this chain should never be very long.
    */
   override def maybeAbsBitPos0b: MaybeULong = {
     val mSuper = super.maybeAbsBitPos0b
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPath.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPath.scala
index 4337a1e..3fff110 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPath.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPath.scala
@@ -54,10 +54,12 @@
     "Expression evaluation failed: %s",
     DiagnosticUtils.getSomeMessage(e).get)
 
-class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kind, recipe: CompiledDPath,
+final class RuntimeExpressionDPath[T <: AnyRef](qn: NamedQName, tt: NodeInfo.Kind, recipe: CompiledDPath,
   dpathText: String,
   ci: DPathCompileInfo,
-  isEvaluatedAbove: Boolean)
+  isEvaluatedAbove: Boolean,
+  override val contentReferencedElementInfos: Set[DPathElementCompileInfo],
+  override val valueReferencedElementInfos: Set[DPathElementCompileInfo])
   extends CompiledExpression[T](qn, dpathText) {
 
   override def targetType = tt
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPathRuntime.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPathRuntime.scala
index d967387..fc3c66d 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPathRuntime.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DPathRuntime.scala
@@ -186,6 +186,7 @@
     dstate.setCurrentValue(v)
   }
   override def toXML = toXML(v.toString)
+
 }
 
 case class IF(predRecipe: CompiledDPath, thenPartRecipe: CompiledDPath, elsePartRecipe: CompiledDPath)
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dsom/CompiledExpression1.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dsom/CompiledExpression1.scala
index 966897f..cfcc53b 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dsom/CompiledExpression1.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dsom/CompiledExpression1.scala
@@ -49,6 +49,11 @@
 import edu.illinois.ncsa.daffodil.api.DaffodilTunableParameters
 import edu.illinois.ncsa.daffodil.api.DaffodilTunableParameters.UnqualifiedPathStepPolicy
 
+trait ContentValueReferencedElementInfoMixin {
+
+  def contentReferencedElementInfos: Set[DPathElementCompileInfo]
+  def valueReferencedElementInfos: Set[DPathElementCompileInfo]
+}
 /**
  * For the DFDL path/expression language, this provides the place to
  * type check the expression (SDE if not properly typed)
@@ -72,7 +77,7 @@
 abstract class CompiledExpression[+T <: AnyRef](
   val qName: NamedQName,
   valueForDebugPrinting: AnyRef)
-  extends Serializable {
+  extends ContentValueReferencedElementInfoMixin with Serializable {
 
   final def toBriefXML(depth: Int = -1) = {
     "'" + prettyExpr + "'"
@@ -126,6 +131,13 @@
   def evaluateForwardReferencing(state: ParseOrUnparseState, whereBlockedLocation: Suspension): Maybe[T]
 
   override def toString(): String = "CompiledExpression(" + valueForDebugPrinting.toString + ")"
+
+}
+
+object ReferencedElementInfos {
+
+  val None = Set.empty.asInstanceOf[Set[DPathElementCompileInfo]]
+
 }
 
 final case class ConstantExpression[+T <: AnyRef](
@@ -156,6 +168,9 @@
 
   def constant: T = value
   def isConstant = true
+
+  override def contentReferencedElementInfos = ReferencedElementInfos.None
+  override def valueReferencedElementInfos = ReferencedElementInfos.None
 }
 
 /**
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator1.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator1.scala
index d3cdebd..6877baa 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator1.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/ElementCombinator1.scala
@@ -106,11 +106,10 @@
       if (pstate.status ne Success) {
         pstate.dataInputStream.discard(startingBitPos)
         return
+      } else {
+        pstate.dataInputStream.reset(startingBitPos)
       }
-      pstate.dataInputStream.reset(startingBitPos)
-    }
-
-    if (patAssertParser.length > 0) {
+    } else if (patAssertParser.length > 0) {
       val startingBitPos = pstate.dataInputStream.mark
       var i: Int = 0
       val size = patAssertParser.size
@@ -243,7 +242,7 @@
   }
 
   def parseBegin(pstate: PState): Unit = {
-    val currentElement = Infoset.newElement(erd)
+    val currentElement = Infoset.newElement(erd).asInstanceOf[DIElement]
 
     log(LogLevel.Debug, "currentElement = %s", currentElement)
     val priorElement = pstate.infoset
@@ -260,8 +259,8 @@
   }
 
   def parseEnd(pstate: PState): Unit = {
-    val currentElement = pstate.thisElement
-    val priorElement = currentElement.parent
+    val currentElement = pstate.infoset
+    val priorElement = currentElement.diParent
 
     if (pstate.status eq Success) {
       val shouldValidate =
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/EvDelimiters.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/EvDelimiters.scala
index c197851..2990943 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/EvDelimiters.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/EvDelimiters.scala
@@ -40,7 +40,9 @@
 import edu.illinois.ncsa.daffodil.processors.parsers.DelimiterTextType
 
 trait DelimiterEvMixin[+T <: AnyRef]
-    extends ExprEvalMixin[String] { self: Evaluatable[T] =>
+  extends ExprEvalMixin[String] { self: Evaluatable[T] =>
+
+  final def isKnownNonEmpty = expr.isKnownNonEmpty
 
   def expr: CompiledExpression[String]
   def converter: Converter[String, List[String]]
@@ -60,14 +62,12 @@
 }
 
 abstract class DelimiterParseEv(delimType: DelimiterTextType.Type, override val expr: CompiledExpression[String], override val trd: TermRuntimeData)
-    extends Evaluatable[Array[DFADelimiter]](trd)
-    with InfosetCachedEvaluatable[Array[DFADelimiter]]
-    with DelimiterEvMixin[Array[DFADelimiter]] {
+  extends Evaluatable[Array[DFADelimiter]](trd)
+  with InfosetCachedEvaluatable[Array[DFADelimiter]]
+  with DelimiterEvMixin[Array[DFADelimiter]] {
 
   override lazy val runtimeDependencies = Nil
 
-  def isKnownNonEmpty = !isConstant || optConstant.get.length > 0
-
   override protected def compute(state: ParseOrUnparseState): Array[DFADelimiter] = {
     if (state.isInstanceOf[UState]) {
       Assert.invariantFailed("State was UState in Parser Evaluatable")
@@ -83,9 +83,9 @@
 }
 
 abstract class DelimiterUnparseEv(delimType: DelimiterTextType.Type, override val expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, override val trd: TermRuntimeData)
-    extends Evaluatable[Option[DFADelimiter]](trd)
-    with InfosetCachedEvaluatable[Option[DFADelimiter]]
-    with DelimiterEvMixin[Option[DFADelimiter]] {
+  extends Evaluatable[Option[DFADelimiter]](trd)
+  with InfosetCachedEvaluatable[Option[DFADelimiter]]
+  with DelimiterEvMixin[Option[DFADelimiter]] {
 
   override lazy val runtimeDependencies = Seq(outputNewLine)
 
@@ -105,37 +105,37 @@
 }
 
 class InitiatorParseEv(expr: CompiledExpression[String], trd: TermRuntimeData)
-    extends DelimiterParseEv(DelimiterTextType.Initiator, expr, trd) {
+  extends DelimiterParseEv(DelimiterTextType.Initiator, expr, trd) {
 
   override val converter = InitiatorCooker
 }
 
 class InitiatorUnparseEv(expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, trd: TermRuntimeData)
-    extends DelimiterUnparseEv(DelimiterTextType.Initiator, expr, outputNewLine, trd) {
+  extends DelimiterUnparseEv(DelimiterTextType.Initiator, expr, outputNewLine, trd) {
 
   override val converter = InitiatorCooker
 }
 
 class TerminatorParseEv(expr: CompiledExpression[String], isLengthKindDelimited: Boolean, trd: TermRuntimeData)
-    extends DelimiterParseEv(DelimiterTextType.Terminator, expr, trd) {
+  extends DelimiterParseEv(DelimiterTextType.Terminator, expr, trd) {
 
   override val converter = if (isLengthKindDelimited) TerminatorCookerNoES else TerminatorCooker
 }
 
 class TerminatorUnparseEv(expr: CompiledExpression[String], isLengthKindDelimited: Boolean, outputNewLine: OutputNewLineEv, trd: TermRuntimeData)
-    extends DelimiterUnparseEv(DelimiterTextType.Terminator, expr, outputNewLine, trd) {
+  extends DelimiterUnparseEv(DelimiterTextType.Terminator, expr, outputNewLine, trd) {
 
   override val converter = if (isLengthKindDelimited) TerminatorCookerNoES else TerminatorCooker
 }
 
 class SeparatorParseEv(expr: CompiledExpression[String], trd: TermRuntimeData)
-    extends DelimiterParseEv(DelimiterTextType.Separator, expr, trd) {
+  extends DelimiterParseEv(DelimiterTextType.Separator, expr, trd) {
 
   override val converter = SeparatorCooker
 }
 
 class SeparatorUnparseEv(expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, trd: TermRuntimeData)
-    extends DelimiterUnparseEv(DelimiterTextType.Separator, expr, outputNewLine, trd) {
+  extends DelimiterUnparseEv(DelimiterTextType.Separator, expr, outputNewLine, trd) {
 
   override val converter = SeparatorCooker
 }
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Evaluatable.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Evaluatable.scala
index 5ce1eaf..342c415 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Evaluatable.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Evaluatable.scala
@@ -50,6 +50,7 @@
 import edu.illinois.ncsa.daffodil.dpath.EvalMode
 import edu.illinois.ncsa.daffodil.dpath.UnparserNonBlocking
 import edu.illinois.ncsa.daffodil.util.MStackOfMaybe
+import edu.illinois.ncsa.daffodil.dsom.ContentValueReferencedElementInfoMixin
 
 /**
  * Generates unique int for use as key into EvalCache
@@ -204,7 +205,7 @@
         // outputValueCalc since we need to maintain the state. Otherwise, it
         // is more memory efficient to just recalculate any evaluatables
         Assert.invariant(state.currentNode.isDefined)
-        val cn = state.currentNode.get
+        val cn = state.infoset
         val termNode = cn match {
           case t: DITerm => t
           case _ => Assert.invariantFailed("current node was not a term.")
@@ -450,7 +451,10 @@
   }
 }
 
-trait ExprEvalMixin[T <: AnyRef] extends DoSDEMixin {
+trait ExprEvalMixin[T <: AnyRef]
+  extends DoSDEMixin with ContentValueReferencedElementInfoMixin {
+
+  protected def expr: CompiledExpression[T]
 
   protected def maybeUseUnparserMode: Maybe[EvalMode]
 
@@ -485,6 +489,9 @@
     expressionResult
   }
 
+  final def contentReferencedElementInfos = expr.contentReferencedElementInfos
+  final def valueReferencedElementInfos = expr.valueReferencedElementInfos
+
 }
 
 /**
@@ -492,10 +499,10 @@
  * of the property.
  */
 abstract class EvaluatableExpression[ExprType <: AnyRef](
-  expr: CompiledExpression[ExprType],
+  override protected val expr: CompiledExpression[ExprType],
   rd: RuntimeData)
-    extends Evaluatable[ExprType](rd)
-    with ExprEvalMixin[ExprType] {
+  extends Evaluatable[ExprType](rd)
+  with ExprEvalMixin[ExprType] {
 
   override lazy val runtimeDependencies = Nil
 
@@ -513,12 +520,10 @@
  * See the cookers for string literals such as TextStandardInfinityRepCooker.
  */
 trait EvaluatableConvertedExpressionMixin[ExprType <: AnyRef, +ConvertedType <: AnyRef]
-    extends ExprEvalMixin[ExprType] { self: Evaluatable[ConvertedType] =>
+  extends ExprEvalMixin[ExprType] { self: Evaluatable[ConvertedType] =>
 
   protected def converter: Converter[ExprType, ConvertedType]
 
-  protected def expr: CompiledExpression[ExprType]
-
   override lazy val runtimeDependencies = Nil
 
   override final def toBriefXML(depth: Int = -1) = if (this.isConstant) this.constValue.toString else expr.toBriefXML(depth)
@@ -543,6 +548,6 @@
   val expr: CompiledExpression[ExprType],
   val converter: Converter[ExprType, ConvertedType],
   rd: RuntimeData)
-    extends Evaluatable[ConvertedType](rd)
-    with EvaluatableConvertedExpressionMixin[ExprType, ConvertedType]
+  extends Evaluatable[ConvertedType](rd)
+  with EvaluatableConvertedExpressionMixin[ExprType, ConvertedType]
 
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Infoset.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Infoset.scala
index 296a012..2858f28 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Infoset.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Infoset.scala
@@ -37,13 +37,6 @@
 import edu.illinois.ncsa.daffodil.util.MaybeBoolean
 import edu.illinois.ncsa.daffodil.util.Maybe
 
-/**
- * Saved for backtracking. Used to restore to prior Infoset element content.
- */
-trait InfosetElementState {
-  // nothing
-}
-
 trait InfosetCommon {
   def toXML(removeHidden: Boolean = true, showFormatInfo: Boolean = false): scala.xml.NodeSeq
 }
@@ -81,20 +74,6 @@
   def isHidden: Boolean
 
   /**
-   * These should maintain a per-thread pool.
-   *
-   * Capture state should obtain an object of the
-   * appropriate type and populate it. Restore should
-   * restore the infoset object per what was saved,
-   * and then release the captured-state-object back
-   * to the pool. The released object should be cleared
-   * (to avoid holding onto references to anything)
-   * when put back into the pool.
-   */
-  def captureState(): InfosetElementState
-  def restoreState(state: InfosetElementState): Unit
-
-  /**
    * Removes child elements that are hidden. Except this element itself,
    * which is not removed even if it is marked hidden.
    */
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/InfosetImpl.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/InfosetImpl.scala
index 092368c..acaf17b 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/InfosetImpl.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/InfosetImpl.scala
@@ -212,9 +212,7 @@
   private def die = throw new InfosetNoInfosetException(Nope)
 
   override def toXML(removeHidden: Boolean = true, showFormatInfo: Boolean = false): scala.xml.NodeSeq = die
-  override def captureState(): InfosetElementState = die
   override def removeHiddenElements(): InfosetElement = die
-  override def restoreState(state: InfosetElementState): Unit = die
 
   override def parent = die
   override def diParent = die
@@ -226,7 +224,6 @@
   override def valid = die
   override def setValid(validity: Boolean): Unit = die
 
-  private var _value: AnyRef = null
   override def dataValue: AnyRef = _value
   override def setDataValue(s: AnyRef): Unit = { _value = asAnyRef(s) }
 
@@ -352,7 +349,6 @@
   private var maybeComputedLength: MaybeULong = MaybeULong.Nope
 
   def copyFrom(other: LengthState) {
-    other.recheckStreams()
     this.maybeStartDataOutputStream = other.maybeStartDataOutputStream
     this.maybeStartPos0bInBits = other.maybeStartPos0bInBits
     this.maybeEndDataOutputStream = other.maybeEndDataOutputStream
@@ -360,6 +356,14 @@
     this.maybeComputedLength = other.maybeComputedLength
   }
 
+  def clear() {
+    maybeStartDataOutputStream = Nope
+    maybeStartPos0bInBits = MaybeULong.Nope
+    maybeEndDataOutputStream = Nope
+    maybeEndPos0bInBits = MaybeULong.Nope
+    maybeComputedLength = MaybeULong.Nope
+  }
+
   protected def throwUnknown: Nothing
 
   /**
@@ -599,27 +603,216 @@
 
 }
 
-trait DIElementState extends InfosetElementState {
-  val contentLength = new ContentLengthState(null)
-  val valueLength = new ValueLengthState(null)
+sealed trait DIElementSharedInterface {
+  def contentLength: ContentLengthState
+  def valueLength: ValueLengthState
+  def restoreInto(e: DIElement): Unit
+  def captureFrom(e: DIElement): Unit
+  def clear(): Unit
 }
 
-class DIComplexState(val isNilled: Boolean, val validity: MaybeBoolean, val lastSlotAdded: Int, val arraySize: MaybeInt)
-  extends DIElementState
+sealed trait DIElementSharedMembersMixin {
 
-case class DISimpleState(var isNilled: Boolean,
-  var isDefaulted: Boolean,
-  var validity: MaybeBoolean,
-  var value: AnyRef //  ,
-  //  var maybeValueLengthInCharacters: MaybeULong,
-  //  var maybeValueLengthInBits: MaybeULong
-  ) extends DIElementState
+  protected final var _contentLength: ContentLengthState = null
+  protected final var _valueLength: ValueLengthState = null
+
+  protected final var _isNilled: Boolean = false
+  protected final var _validity: MaybeBoolean = MaybeBoolean.Nope
+
+  protected def allocContentLength: ContentLengthState
+  protected def allocValueLength: ValueLengthState
+
+  /**
+   * Copy method keeps these objects null
+   * to avoid allocation unless they are really needed.
+   */
+  final protected def copyContentLengthFrom(e: DIElementSharedMembersMixin) {
+    if (e._contentLength eq null)
+      if (this._contentLength eq null) {
+        // do nothing
+      } else {
+        this._contentLength = null
+      }
+    else {
+      if (this._contentLength eq null) {
+        this._contentLength = allocContentLength
+      }
+      this._contentLength.copyFrom(e._contentLength)
+    }
+  }
+
+  /**
+   * Copy method keeps these objects null
+   * to avoid allocation unless they are really needed.
+   */
+  final protected def copyValueLengthFrom(e: DIElementSharedMembersMixin) {
+    if (e._valueLength eq null)
+      if (this._valueLength eq null) {
+        // do nothing
+      } else {
+        this._valueLength = null
+      }
+    else {
+      if (this._valueLength eq null) {
+        this._valueLength = allocValueLength
+      }
+      this._valueLength.copyFrom(e._valueLength)
+    }
+  }
+
+  /*
+   * Initialized on demand
+   */
+  final def contentLength = {
+    if (_contentLength eq null) {
+      _contentLength = allocContentLength
+    }
+    _contentLength
+  }
+
+  final def valueLength = {
+    if (_valueLength eq null) {
+      _valueLength = allocValueLength
+    }
+    _valueLength
+  }
+
+}
+
+sealed abstract class DIElementState
+  extends DIElementSharedInterface
+  with DIElementSharedImplMixin {
+
+  final override protected def allocContentLength = new ContentLengthState(null)
+  final override protected def allocValueLength = new ValueLengthState(null)
+
+}
+
+sealed trait DIElementSharedImplMixin
+  extends DIElementSharedInterface
+  with DIElementSharedMembersMixin {
+
+  override def restoreInto(e: DIElement) {
+    e._isNilled = this._isNilled
+    e._validity = this._validity
+
+    e copyContentLengthFrom (this)
+    e.copyValueLengthFrom(this)
+  }
+
+  override def captureFrom(e: DIElement) {
+    this._isNilled = e._isNilled
+    this._validity = e._validity
+
+    this.copyContentLengthFrom(e)
+    this.copyValueLengthFrom(e)
+  }
+
+  override def clear() {
+    this._isNilled = false
+    this._validity = MaybeBoolean.Nope
+    contentLength.clear()
+    valueLength.clear()
+  }
+
+}
+
+sealed trait DIComplexSharedMembersMixin {
+
+  final var _lastSlotAdded: Int = -1
+  final var _arraySize: MaybeInt = MaybeInt.Nope
+}
+
+sealed trait DIComplexSharedImplMixin
+  extends DIElementSharedInterface
+  with DIComplexSharedMembersMixin {
+
+  abstract override def restoreInto(e: DIElement) {
+    val c = e.asInstanceOf[DIComplex]
+    c.restoreFrom(this)
+    c._lastSlotAdded = this._lastSlotAdded
+    super.restoreInto(e)
+  }
+
+  abstract override def captureFrom(e: DIElement) {
+    val c = e.asInstanceOf[DIComplex]
+    c.captureInto(this)
+    this._lastSlotAdded = c._lastSlotAdded
+    super.captureFrom(e)
+  }
+
+  abstract override def clear() {
+    _lastSlotAdded = -1
+    _arraySize = MaybeInt.Nope
+    super.clear()
+  }
+}
+
+final class DIComplexState private ()
+  extends DIElementState
+  with DIElementSharedImplMixin
+  with DIComplexSharedImplMixin
+
+object DIComplexState {
+  def apply() = { val c = new DIComplexState(); c.clear(); c }
+}
+
+sealed trait DISimpleSharedMembersMixin {
+
+  protected var _isDefaulted: Boolean = false
+
+  protected var _value: AnyRef = null
+}
+
+sealed trait DISimpleSharedImplMixin
+  extends DIElementSharedInterface
+  with DISimpleSharedMembersMixin {
+
+  abstract override def restoreInto(e: DIElement) {
+    super.restoreInto(e)
+    val s = e.asInstanceOf[DISimple]
+    s._isDefaulted = this._isDefaulted
+    s._value = this._value
+  }
+
+  abstract override def captureFrom(e: DIElement) {
+    super.captureFrom(e)
+    val s = e.asInstanceOf[DISimple]
+    this._isDefaulted = s._isDefaulted
+    this._value = s._value
+  }
+
+  abstract override def clear() {
+    super.clear()
+    _isDefaulted = false
+    _value = null
+  }
+}
+
+final class DISimpleState private ()
+  extends DIElementState
+  with DIElementSharedImplMixin
+  with DISimpleSharedImplMixin
+
+object DISimpleState {
+  def apply() = { val s = new DISimpleState(); s.clear(); s }
+}
 
 /**
  * Base for non-array elements. That is either scalar or optional (
  * minOccurs 0, maxOccurs 1)
  */
-sealed trait DIElement extends DINode with DITerm with InfosetElement {
+sealed trait DIElement
+  extends DINode
+  with DITerm
+  with InfosetElement
+  with DIElementSharedImplMixin {
+
+  final override protected def allocContentLength = new ContentLengthState(this)
+  final override protected def allocValueLength = new ValueLengthState(this)
+
+  def isSimple: Boolean
+  def isComplex: Boolean
   override final def name: String = erd.name
   override final def namespace: NS = erd.targetNamespace
   override final def namedQName = erd.namedQName
@@ -682,10 +875,8 @@
 
   final def runtimeData = erd
   protected final var _parent: InfosetComplexElement = null
-  protected final var _isNilled: Boolean = false
-  protected final var _isNilledSet: Boolean = false
 
-  protected final var _validity: MaybeBoolean = MaybeBoolean.Nope
+  protected final var _isNilledSet: Boolean = false
 
   override def parent = _parent
   def diParent = _parent.asInstanceOf[DIComplex]
@@ -775,20 +966,6 @@
     writer.write("\n")
   }
 
-  val contentLength = new ContentLengthState(this)
-  val valueLength = new ValueLengthState(this)
-
-  override def restoreState(st: InfosetElementState): Unit = {
-    val ss = st.asInstanceOf[DIElementState]
-    this.contentLength.copyFrom(ss.contentLength)
-    this.valueLength.copyFrom(ss.valueLength)
-  }
-
-  protected final def captureStateInto(st: InfosetElementState) {
-    val ss = st.asInstanceOf[DIElementState]
-    ss.contentLength.copyFrom(this.contentLength)
-    ss.valueLength.copyFrom(this.valueLength)
-  }
 }
 
 // This is not a mutable collection class on purpose.
@@ -896,13 +1073,14 @@
 
 sealed class DISimple(override val erd: ElementRuntimeData)
   extends DIElement
+  with DISimpleSharedImplMixin
   with InfosetSimpleElement {
 
+  final override def isSimple = true
+  final override def isComplex = false
+
   def filledSlots: IndexedSeq[DINode] = IndexedSeq.empty
 
-  protected var _isDefaulted: Boolean = false
-
-  private var _value: AnyRef = null
   private var _stringRep: String = null
 
   override def children: Stream[DINode] = Stream.Empty
@@ -1136,72 +1314,6 @@
     }
   }
 
-  //TODO: make these use a pool of these DISimpleState objects
-  // so as to avoid allocating and discarding when really we only need
-  // a handful of them and they obey a stack discipline.
-  //
-  override def captureState(): InfosetElementState = {
-    val st = DISimpleState(_isNilled, _isDefaulted, _validity, _value //        ,
-    //        this.maybeValueLengthInCharacters_,
-    //        this.maybeValueLengthInBits_
-    )
-    captureStateInto(st)
-    st
-  }
-
-  override def restoreState(st: InfosetElementState): Unit = {
-    super.restoreState(st)
-    val ss = st.asInstanceOf[DISimpleState]
-    _isNilled = ss.isNilled
-    _validity = ss.validity
-    _isDefaulted = ss.isDefaulted
-    _value = ss.value
-    //    maybeValueLengthInCharacters_ = ss.maybeValueLengthInCharacters
-    //    maybeValueLengthInBits_ = ss.maybeValueLengthInBits
-  }
-  //
-  //  private var maybeValueLengthInCharacters_ : MaybeULong = MaybeULong.Nope
-  //  private var maybeValueLengthInBits_ : MaybeULong = MaybeULong.Nope
-  //
-  //  def valueLengthInCharacters: ULong = {
-  //    erd.SDE("dfdl:valueLength with length units 'characters' is not supported.")
-  //    // TODO: when fixing the above, consider that parsers and unparsers that deal with text
-  //    // must all participate in keeping track of number of characters. At runtime, if the
-  //    // element is not scannable, then units of characters isn't meaningful.
-  //    //
-  //    // Also: keep in mind that valueLength *includes* escape characters, escape-escape, and escapeBlockStart/End characters,
-  //    // but excludes padding characters.
-  //    //
-  //    if (maybeValueLengthInCharacters_.isDefined) maybeValueLengthInCharacters_.getULong
-  //    else throw new InfosetValueLengthUnknownException(this, this.runtimeData)
-  //  }
-  //
-  //  def valueLengthInBits: ULong = {
-  //    if (maybeValueLengthInBits_.isDefined) maybeValueLengthInBits_.getULong
-  //    else throw new InfosetValueLengthUnknownException(this, this.runtimeData)
-  //  }
-  //
-  //  def valueLengthInBytes: ULong = {
-  //    // TODO: assert check for length in bytes makes sense - length units is bytes, or is characters, but characters
-  //    // are byte based (that is not 7-bit or 6-bit)
-  //    // or is bits, but for some reason we know it's a multiple of 8.
-  //    // For now, this is just going to round up to the next number of bytes whenever there is a frag byte.
-  //    val clbits = valueLengthInBits
-  //    val wholeBytes = math.ceil(clbits.toDouble / 8.0).toLong
-  //    ULong(wholeBytes)
-  //  }
-  //
-  //  def setValueLengthInBits(len: ULong) {
-  //    maybeValueLengthInBits_ = MaybeULong(len.longValue)
-  //  }
-  //
-  //  def setValueLengthInCharacters(len: ULong) {
-  //    maybeValueLengthInCharacters_ = MaybeULong(len.longValue)
-  //  }
-  //
-  //  def setValueLengthInBytes(len: ULong) {
-  //    maybeValueLengthInBits_ = MaybeULong(len * 8)
-  //  }
 }
 /**
  * Arrays and complex elements have a notion of being finalized, when unparsing.
@@ -1242,10 +1354,15 @@
  * The DIArray object's length gives the number of occurrences.
  */
 sealed class DIComplex(override val erd: ElementRuntimeData)
-  extends DIElement with InfosetComplexElement
+  extends DIElement
+  with DIComplexSharedImplMixin
+  with InfosetComplexElement
   with DIFinalizable // with HasModelGroupMixin
   { diComplex =>
 
+  final override def isSimple = false
+  final override def isComplex = true
+
   private lazy val nfe = new InfosetComplexElementNotFinalException(this)
 
   override def requireFinal {
@@ -1275,8 +1392,6 @@
     slots
   }
 
-  private var _lastSlotAdded = -1
-
   override lazy val filledSlots: IndexedSeq[DINode] = slots.filter { _ ne null }
 
   override def children = _slots.map { s => if (Maybe.WithNulls.isDefined(s)) Some(s) else None }.flatten.toStream
@@ -1364,10 +1479,11 @@
     this
   }
 
-  //TODO: make these use a thread-local pool so that we avoid allocating
-  //these objects that obey a stack discipline.
-  final override def captureState(): InfosetElementState = {
-    val arrSize =
+  final def captureInto(cs: DIComplexSharedImplMixin) {
+    Assert.invariant(_arraySize == MaybeInt.Nope)
+    Assert.invariant(cs._arraySize == MaybeInt.Nope)
+
+    cs._arraySize =
       if (_lastSlotAdded >= 0) {
         _slots(_lastSlotAdded) match {
           case arr: DIArray => MaybeInt(arr.length.toInt)
@@ -1376,26 +1492,20 @@
       } else {
         MaybeInt.Nope
       }
-    val st = new DIComplexState(_isNilled, _validity, _lastSlotAdded, arrSize)
-    captureStateInto(st)
-    st
   }
 
-  final override def restoreState(st: InfosetElementState): Unit = {
-    super.restoreState(st)
-    val ss = st.asInstanceOf[DIComplexState]
-    _isNilled = ss.isNilled
-    _validity = ss.validity
+  final def restoreFrom(cs: DIComplexSharedImplMixin) {
+    Assert.invariant(_arraySize == MaybeInt.Nope)
 
     var i = _lastSlotAdded
-    while (i > ss.lastSlotAdded) {
+    while (i > cs._lastSlotAdded) {
       _slots(i) = null
       i -= 1
     }
-    _lastSlotAdded = ss.lastSlotAdded
+    _lastSlotAdded = cs._lastSlotAdded
 
-    if (ss.arraySize.isDefined) {
-      _slots(_lastSlotAdded).asInstanceOf[DIArray].reduceToSize(ss.arraySize.get)
+    if (cs._arraySize.isDefined) {
+      _slots(_lastSlotAdded).asInstanceOf[DIArray].reduceToSize(cs._arraySize.get)
     }
   }
 
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/PState.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/PState.scala
index 800de45..4bb0658 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/PState.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/PState.scala
@@ -72,7 +72,7 @@
     obj
   }
 
-  class Mark {
+  final class Mark {
 
     var arrayIndexStackMark: MStack.Mark = _
     var groupIndexStackMark: MStack.Mark = _
@@ -88,13 +88,13 @@
       occursBoundsStackMark = MStack.nullMark
     }
 
-    def setMarkFrom(mp: MPState) {
+    def captureFrom(mp: MPState) {
       arrayIndexStackMark = mp.arrayIndexStack.mark
       groupIndexStackMark = mp.groupIndexStack.mark
       childIndexStackMark = mp.childIndexStack.mark
       occursBoundsStackMark = mp.occursBoundsStack.mark
     }
-    def resetFromMark(mp: MPState) {
+    def restoreInto(mp: MPState) {
       mp.arrayIndexStack.reset(this.arrayIndexStackMark)
       mp.groupIndexStack.reset(this.groupIndexStackMark)
       mp.childIndexStack.reset(this.childIndexStackMark)
@@ -336,7 +336,7 @@
 
   private lazy val infoset_ : Maybe[DIElement] = Nope
 
-  def infoset: InfosetItem =
+  def infoset: DIElement =
     if (infoset_.isDefined)
       infoset_.value
     else
@@ -348,14 +348,14 @@
   private val occursBoundsStack_ = MStackOfLong()
   def occursBoundsStack: MStackOfLong = occursBoundsStack_
 
-  def thisElement: InfosetElement = infoset.asInstanceOf[InfosetElement]
+  def thisElement = infoset
 
   // Members declared in edu.illinois.ncsa.daffodil.processors.StateForDebugger
   def currentLocation: DataLocation = Assert.usageError("Not to be used.")
 }
 
 final class PState private (
-  var infoset: InfosetItem,
+  var infoset: DIElement,
   var dataInputStream: DataInputStream,
   vmap: VariableMap,
   status: ProcessorResult,
@@ -365,9 +365,9 @@
   var delimitedParseResult: Maybe[dfa.ParseResult])
   extends ParseOrUnparseState(vmap, diagnosticsArg, One(dataProcArg), status) {
 
-  override def currentNode = Maybe(infoset.asInstanceOf[DINode])
+  override def currentNode = Maybe(infoset)
 
-  val discriminatorStack = MStackOfBoolean()
+  private val discriminatorStack = MStackOfBoolean()
   discriminatorStack.push(false)
 
   override def dataStream = One(dataInputStream)
@@ -383,7 +383,7 @@
   }
 
   override def hasInfoset = true
-  def thisElement = infoset.asInstanceOf[InfosetElement]
+  def thisElement = infoset
 
   override def groupPos = mpstate.groupPos
   override def arrayPos = mpstate.arrayPos
@@ -395,13 +395,13 @@
   def mark: PState.Mark = {
     // threadCheck()
     val m = markPool.getFromPool
-    m.assignFromPState(this)
+    m.captureFrom(this)
     m
   }
 
   def reset(m: PState.Mark) {
     // threadCheck()
-    m.resetOntoPState(this)
+    m.restoreInto(this)
     m.clear()
     markPool.returnToPool(m)
   }
@@ -447,7 +447,17 @@
     dataInputStream.setBitLimit0b(MaybeULong(bitLimit0b))
   }
 
-  def setParent(newParent: InfosetItem) {
+  /**
+   * This takes newParent as DIElement, not DIComplex, because there is code
+   * where we don't know whether the node is simple or complex but we set it as
+   * the parent anyway. If simple children will simply not be appended.
+   *
+   * But this invariant that there is always a parent we could append a child into
+   * is being maintained. THis invariant starts at the very top as there is a
+   * Document which is the parent of the root element. So there's no time when there
+   * isn't a parent there.
+   */
+  def setParent(newParent: DIElement) {
     this.infoset = newParent
   }
 
@@ -482,22 +492,6 @@
     discriminatorStack.push(disc)
   }
 
-  //  def setPos(bitPos: Long) {
-  ////    val newInStream = inStream.withPos(bitPos)
-  ////    this.inStream = newInStream
-  //    dataInputStream.asInstanceOf[ByteBufferDataInputStream].setBitPos0b(bitPos)
-  //  }
-
-  def captureInfosetElementState = {
-    // threadCheck()
-    thisElement.captureState()
-  }
-
-  def restoreInfosetElementState(st: InfosetElementState) = {
-    // threadCheck()
-    thisElement.restoreState(st)
-  }
-
   final def notifyDebugging(flag: Boolean) {
     // threadCheck()
     dataInputStream.setDebugging(flag)
@@ -515,46 +509,52 @@
 
     def bitPos0b = disMark.bitPos0b
 
-    var infosetState: InfosetElementState = _
+    val simpleElementState = DISimpleState()
+    val complexElementState = DIComplexState()
     var disMark: DataInputStream.Mark = _
     var variableMap: VariableMap = _
     var status: ProcessorResult = _
     var diagnostics: List[Diagnostic] = _
-    var discriminatorStackMark: MStack.Mark = _
     var delimitedParseResult: Maybe[dfa.ParseResult] = Nope
 
     val mpStateMark = new MPState.Mark
 
     def clear() {
-      infosetState = null
+      simpleElementState.clear()
+      complexElementState.clear()
       disMark = null
       variableMap = null
       status = null
       diagnostics = null
-      discriminatorStackMark = MStack.nullMark
       delimitedParseResult = Nope
       mpStateMark.clear()
     }
 
-    def assignFromPState(ps: PState) {
-      this.infosetState = ps.captureInfosetElementState
+    def captureFrom(ps: PState) {
+      val e = ps.thisElement
+      if (e.isSimple)
+        simpleElementState.captureFrom(e)
+      else
+        complexElementState.captureFrom(e)
       this.disMark = ps.dataInputStream.mark
       this.variableMap = ps.variableMap
       this.status = ps.status
       this.diagnostics = ps.diagnostics
-      this.discriminatorStackMark = ps.discriminatorStack.mark
-      this.mpStateMark.setMarkFrom(ps.mpstate)
+      this.mpStateMark.captureFrom(ps.mpstate)
     }
 
-    def resetOntoPState(ps: PState) {
-      ps.restoreInfosetElementState(this.infosetState)
+    def restoreInto(ps: PState) {
+      val e = ps.thisElement
+      e match {
+        case s: DISimple => simpleElementState.restoreInto(e)
+        case c: DIComplex => complexElementState.restoreInto(e)
+      }
       ps.dataInputStream.reset(this.disMark)
       ps.setVariableMap(this.variableMap)
       ps.status_ = this.status
       ps.diagnostics = this.diagnostics
-      ps.discriminatorStack.reset(this.discriminatorStackMark)
       ps.delimitedParseResult = this.delimitedParseResult
-      mpStateMark.resetFromMark(ps.mpstate)
+      mpStateMark.restoreInto(ps.mpstate)
     }
 
   }
@@ -571,7 +571,7 @@
     dis: DataInputStream,
     dataProc: DFDL.DataProcessor): PState = {
 
-    val doc = Infoset.newDocument(root)
+    val doc = Infoset.newDocument(root).asInstanceOf[DIElement]
     val variables = dataProc.getVariables
     val status = Success
     val diagnostics = Nil
@@ -595,7 +595,7 @@
     val diagnostics = Nil
     val mutablePState = MPState()
 
-    val newState = new PState(doc, dis, variables, status, diagnostics, mutablePState,
+    val newState = new PState(doc.asInstanceOf[DIElement], dis, variables, status, diagnostics, mutablePState,
       dataProc.asInstanceOf[DataProcessor], Nope)
     newState
   }
@@ -626,5 +626,4 @@
       ByteBufferDataInputStream.fromByteChannel(input, bitOffset, bitLengthLimit, bitOrder)
     createInitialPState(root, dis, dataProc)
   }
-
 }
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Parser.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Parser.scala
index f57000e..685902c 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Parser.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Parser.scala
@@ -223,17 +223,9 @@
     var i: Int = 0
     while (i < numChildParsers) {
       val parser = childParsers(i)
-
-      // val beforeParse = pstate.dataInputStream.mark
       parser.parse1(pstate)
-      //Assert.invariant(pstate.dataProc.handlers == handlers)
-      if (pstate.status ne Success) {
-        // pstate.dataInputStream.reset(beforeParse)
+      if (pstate.status ne Success)
         return
-      } else {
-        // pstate.dataInputStream.discard(beforeParse)
-      }
-
       i += 1
     }
   }
@@ -248,63 +240,69 @@
   override def nom = "alt"
 
   def parse(pstate: PState): Unit = {
+    var pBefore: PState.Mark = null
+
     pstate.pushDiscriminator
-    var pBefore = pstate.mark
     var diagnostics: Seq[Diagnostic] = Nil
-    val cloneNode = pstate.captureInfosetElementState // we must undo side-effects on the JDOM if we backtrack.
-    childParsers.foreach { parser =>
-      {
-        log(LogLevel.Debug, "Trying choice alternative: %s", parser)
-        try {
-          pstate.reset(pBefore)
-          pBefore = pstate.mark
-          parser.parse1(pstate)
-        } catch {
-          case rsde: RuntimeSchemaDefinitionError => { pstate.discard(pBefore); throw rsde }
-        }
-        if (pstate.status eq Success) {
-          log(LogLevel.Debug, "Choice alternative success: %s", parser)
-          pstate.popDiscriminator
-          pstate.discard(pBefore)
-          return
-        }
+    var i = 0
+    var parser: Parser = null
+    val limit = childParsers.length
+    var returnFlag = false
+    while (!returnFlag && i < limit) {
+      parser = childParsers(i)
+      i += 1
+      log(LogLevel.Debug, "Trying choice alternative: %s", parser)
+      pBefore = pstate.mark
+      parser.parse1(pstate)
+      if (pstate.status eq Success) {
+        log(LogLevel.Debug, "Choice alternative success: %s", parser)
+        pstate.discard(pBefore)
+        pBefore = null
+        returnFlag = true
+      } else {
         // If we get here, then we had a failure
         log(LogLevel.Debug, "Choice alternative failed: %s", parser)
         //
-        //
-        // Unwind any side effects on the Infoset
-        //
-        pstate.restoreInfosetElementState(cloneNode)
-        //
         // capture diagnostics
         //
         val diag = new ParseAlternativeFailed(context.schemaFileLocation, pstate, pstate.diagnostics)
         diagnostics = diag +: diagnostics
-
+        //
         // check for discriminator evaluated to true.
+        //
         if (pstate.discriminator == true) {
           log(LogLevel.Debug, "Failure, but discriminator true. Additional alternatives discarded.")
           // If so, then we don't run the next alternative, we
           // consume this discriminator status result (so it doesn't ripple upward)
-          // and return the failed state withall the diagnostics.
+          // and return the failed state with all the diagnostics.
           //
           val allDiags = new AltParseFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
-          pstate.discard(pBefore)
+          pstate.discard(pBefore) // because disc set, we don't unwind side effects on input stream & infoset
+          pBefore = null
           pstate.setFailed(allDiags)
-          pstate.popDiscriminator
-          return
+          returnFlag = true
+        } else {
+          //
+          // Here we have a failure, but no discriminator was set, so we try the next alternative.
+          // Which means we just go around the loop
+          //
+          // But we have to unwind side-effects on input-stream, infoset, variables, etc.
+          pstate.reset(pBefore)
+          pBefore = null
+          returnFlag = false
         }
-        //
-        // Here we have a failure, but no discriminator was set, so we try the next alternative.
-        // Which means we just go around the loop
       }
     }
-    // Out of alternatives. All of them failed.
+    Assert.invariant(i <= limit)
+    if (returnFlag == false) {
+      Assert.invariant(i == limit)
+      // Out of alternatives. All of them failed.
+      val allDiags = new AltParseFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
+      pstate.setFailed(allDiags)
+      log(LogLevel.Debug, "All AltParser alternatives failed.")
+    }
 
-    pstate.reset(pBefore)
-    val allDiags = new AltParseFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
-    pstate.setFailed(allDiags)
-    log(LogLevel.Debug, "All AltParser alternatives failed.")
+    Assert.invariant(pBefore eq null)
     pstate.popDiscriminator
   }
 
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Runtime.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Runtime.scala
index 972a6c1..5d1c1d1 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Runtime.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Runtime.scala
@@ -202,7 +202,6 @@
       doParse(ssrd.parser, state)
       val pr = new ParseResult(this, state)
       pr.validateResult(state)
-
       val s = state
       val dp = s.dataProc
       val ssrdParser = ssrd.parser
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/RuntimeData.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/RuntimeData.scala
index a7ad87a..18eaf46 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/RuntimeData.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/RuntimeData.scala
@@ -341,6 +341,8 @@
   lazy val optTruncateSpecifiedLengthString = optTruncateSpecifiedLengthStringArg
   lazy val outputValueCalcExpr = outputValueCalcExprArg
 
+  def isReferencedByExpressions = !notReferencedByExpressions
+
   override def preSerialization: Unit = {
     super.preSerialization
     parent
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/RepParsers.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/RepParsers.scala
index 974934d..1eead0e 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/RepParsers.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/RepParsers.scala
@@ -34,7 +34,6 @@
 
 import edu.illinois.ncsa.daffodil.api.DaffodilTunableParameters
 import edu.illinois.ncsa.daffodil.dpath.AsIntConverters
-import edu.illinois.ncsa.daffodil.equality.TypeEqual
 import edu.illinois.ncsa.daffodil.equality.ViewEqual
 import edu.illinois.ncsa.daffodil.exceptions.Assert
 import edu.illinois.ncsa.daffodil.processors.ElementRuntimeData
@@ -128,56 +127,60 @@
   extends RepParser(n, rParser, erd, "AtMostTotalN") {
 
   def parseAllRepeats(initialState: PState): Unit = {
-    val startState = initialState.mark
-    var priorState = initialState.mark
-    val pstate = initialState
-    while (pstate.mpstate.arrayPos <= intN) {
-      // Since each one could fail, each is a new point of uncertainty.
-      //
-      // save the state of the infoset
-      //
-      val cloneNode = pstate.captureInfosetElementState
-      val infosetElement = pstate.infoset
+    if (initialState.mpstate.arrayPos <= intN) {
+      val startState = initialState.mark
+      var priorState = initialState.mark
+      val pstate = initialState
+      var returnFlag = false
+      while (!returnFlag && (pstate.mpstate.arrayPos <= intN)) {
+        // Since each one could fail, each is a new point of uncertainty.
 
-      pstate.pushDiscriminator
+        pstate.pushDiscriminator
 
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+        if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
 
-      rParser.parse1(pstate)
+        rParser.parse1(pstate)
 
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+        if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
 
-      if (pstate.status ne Success) {
-        //
-        // Did not succeed
-        //
-        // Was a discriminator set?
-        //
-        if (pstate.discriminator == true) {
-          // we fail the whole RepUnbounded, because there was a discriminator set
-          // before the failure.
-          // pstate.popDiscriminator // pop happens when we reset.
-          pstate.reset(startState)
-          return
+        if (pstate.status ne Success) {
+          //
+          // Did not succeed
+          //
+          // Was a discriminator set?
+          //
+          if (pstate.discriminator == true) {
+            // we fail the whole RepUnbounded, because there was a discriminator set
+            // before the failure.
+            pstate.reset(startState)
+            pstate.discard(priorState)
+            returnFlag = true
+          } else {
+            //
+            // backout any element appended as part of this attempt.
+            //
+            pstate.reset(priorState)
+            pstate.discard(startState)
+            returnFlag = true // success at prior state.
+          }
+        } else {
+          //
+          // Success
+          //
+          pstate.discard(priorState)
+          priorState = pstate.mark
+          pstate.mpstate.moveOverOneArrayIndexOnly
+          returnFlag = false
         }
-        //
-        // backout any element appended as part of this attempt.
-        //
-        pstate.infoset = infosetElement
-        pstate.restoreInfosetElementState(cloneNode)
-        pstate.reset(priorState)
-        pstate.discard(startState)
-        return // success at prior state.
+
+        pstate.popDiscriminator
       }
-      //
-      // Success
-      //
-      pstate.discard(priorState)
-      priorState = pstate.mark
-      pstate.mpstate.moveOverOneArrayIndexOnly
-      pstate.popDiscriminator
+      if (returnFlag == false) {
+        // we exited the loop due to arrayPos hitting the upper limit
+        pstate.discard(priorState)
+        pstate.discard(startState)
+      }
     }
-    pstate.discard(startState)
   }
 }
 
@@ -198,12 +201,12 @@
   extends RepParser(-1, rParser, erd, "Unbounded") {
 
   def parseAllRepeats(initialState: PState): Unit = {
-    Assert.invariant(initialState.status =:= Success)
+    Assert.invariant(initialState.status eq Success)
     val startState = initialState.mark
     val pstate = initialState
     var priorState = initialState.mark
-
-    while (pstate.status eq Success) {
+    var returnFlag = false
+    while (!returnFlag && (pstate.status eq Success)) {
 
       //      erd.maxOccurs.foreach { maxOccurs =>
       //        if ((occursCountKind == OccursCountKind.Implicit) &&
@@ -222,8 +225,6 @@
       //        }
       //      }
 
-      val cloneNode = pstate.captureInfosetElementState
-      val infosetElement = pstate.infoset
       //
       // Every parse is a new point of uncertainty.
       pstate.pushDiscriminator
@@ -239,37 +240,39 @@
         if (pstate.discriminator == true) {
           // we fail the whole RepUnbounded, because there was a discriminator set
           // before the failure.
-          pstate.popDiscriminator
           pstate.reset(startState)
-          return
+          pstate.discard(priorState)
+        } else {
+          //
+          // no discriminator, so suppress the failure. Loop terminated with prior element.
+          //
+
+          log(LogLevel.Debug, "Failure suppressed. This is normal termination of a occursCountKind='parsed' array.")
+          pstate.reset(priorState)
+          pstate.discard(startState)
         }
-        //
-        // no discriminator, so suppress the failure. Loop terminated with prior element.
-        //
-        pstate.infoset = infosetElement
-        pstate.restoreInfosetElementState(cloneNode)
-        log(LogLevel.Debug, "Failure suppressed. This is normal termination of a occursCountKind='parsed' array.")
-        pstate.reset(priorState)
-        pstate.discard(startState)
-        return // note that it has the prior point of uncertainty. No restore needed.
+        returnFlag = true
+      } else {
+        // Success
+        // Need to check for forward progress
+        if (pstate.bitPos =#= priorState.bitPos0b) {
+          pstate.discard(priorState) // didn't move, but might have assigned variables, have to undo those.
+          pstate.discard(startState)
+          PE(pstate,
+            "RepUnbounded - No forward progress at byte %s. Attempt to parse %s " +
+              "succeeded but consumed no data.\nPlease re-examine your schema to correct this infinite loop.",
+            pstate.bytePos, erd.prettyName)
+          returnFlag = true
+        } else {
+          pstate.discard(priorState)
+          priorState = pstate.mark
+          pstate.mpstate.moveOverOneArrayIndexOnly
+          returnFlag = false
+        }
       }
-      // Success
-      // Need to check for forward progress
-      if (pstate.bitPos =#= priorState.bitPos0b) {
-        pstate.discard(priorState) // didn't move, but might have assigned variables.
-        pstate.discard(startState)
-        PE(pstate,
-          "RepUnbounded - No forward progress at byte %s. Attempt to parse %s " +
-            "succeeded but consumed no data.\nPlease re-examine your schema to correct this infinite loop.",
-          pstate.bytePos, erd.prettyName)
-        return
-      }
-      pstate.discard(priorState)
-      priorState = pstate.mark
-      pstate.mpstate.moveOverOneArrayIndexOnly // was pstate, not pNext....why?
-      pstate.popDiscriminator // point of uncertainty has been resolved.
+      pstate.popDiscriminator
     }
-    Assert.invariantFailed("Unbounded loop terminated wrong")
+    Assert.invariant(returnFlag == true)
   }
 }
 
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/SpecifiedLengthParsers.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/SpecifiedLengthParsers.scala
index b894aa3..ca720e2 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/SpecifiedLengthParsers.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/SpecifiedLengthParsers.scala
@@ -40,7 +40,6 @@
 import edu.illinois.ncsa.daffodil.processors.PState
 import edu.illinois.ncsa.daffodil.processors.Evaluatable
 import edu.illinois.ncsa.daffodil.processors.Success
-import edu.illinois.ncsa.daffodil.processors.DIElement
 import edu.illinois.ncsa.daffodil.util.OnStack
 import java.util.regex.Matcher
 import edu.illinois.ncsa.daffodil.exceptions.Assert
@@ -236,7 +235,7 @@
 
   override def parse(state: PState) {
     val dis = state.dataInputStream
-    val elem = state.currentNode.get.asInstanceOf[DIElement]
+    val elem = state.infoset
     elem.contentLength.setAbsStartPos0bInBits(ULong(dis.bitPos0b))
   }
 }
@@ -248,7 +247,7 @@
 
   override def parse(state: PState) {
     val dis = state.dataInputStream
-    val elem = state.currentNode.get.asInstanceOf[DIElement]
+    val elem = state.infoset
     elem.contentLength.setAbsEndPos0bInBits(ULong(dis.bitPos0b))
   }
 }
@@ -260,7 +259,7 @@
 
   override def parse(state: PState) {
     val dis = state.dataInputStream
-    val elem = state.currentNode.get.asInstanceOf[DIElement]
+    val elem = state.infoset
     elem.valueLength.setAbsStartPos0bInBits(ULong(dis.bitPos0b))
   }
 }
@@ -272,7 +271,7 @@
 
   override def parse(state: PState) {
     val dis = state.dataInputStream
-    val elem = state.currentNode.get.asInstanceOf[DIElement]
+    val elem = state.infoset
     elem.valueLength.setAbsEndPos0bInBits(ULong(dis.bitPos0b))
   }
 }
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/StringLengthParsers.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/StringLengthParsers.scala
index 5deacac..4bf19fe 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/StringLengthParsers.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/StringLengthParsers.scala
@@ -39,7 +39,6 @@
 import edu.illinois.ncsa.daffodil.processors.TextParserRuntimeMixin
 import edu.illinois.ncsa.daffodil.util.MaybeChar
 import edu.illinois.ncsa.daffodil.util.Misc
-import edu.illinois.ncsa.daffodil.processors.DIElement
 import passera.unsigned.ULong
 import edu.illinois.ncsa.daffodil.processors.CharsetEv
 
@@ -79,7 +78,7 @@
   def charsetEv: CharsetEv
 
   final def captureValueLength(state: PState, startBitPos0b: ULong, endBitPos0b: ULong) {
-    val elem = state.currentNode.get.asInstanceOf[DIElement]
+    val elem = state.infoset
     elem.valueLength.setAbsStartPos0bInBits(startBitPos0b)
     elem.valueLength.setAbsEndPos0bInBits(endBitPos0b)
   }
diff --git a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section06/namespaces/multi_base_03.dfdl.xsd b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section06/namespaces/multi_base_03.dfdl.xsd
index 09a657a..c0641b4 100644
--- a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section06/namespaces/multi_base_03.dfdl.xsd
+++ b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section06/namespaces/multi_base_03.dfdl.xsd
@@ -40,7 +40,8 @@
         separatorPosition="infix" ignoreCase="no" separatorSuppressionPolicy="anyEmpty" representation="text" 
         textNumberRep="standard" lengthKind="delimited" encoding="ASCII"
         alignment="implicit" alignmentUnits="bytes" trailingSkip="0" outputNewLine="%LF;"
-        fillByte="%SP;" truncateSpecifiedLengthString="yes" escapeSchemeRef=""/>
+        fillByte="%SP;" truncateSpecifiedLengthString="yes" escapeSchemeRef=""
+        textPadKind='none'/>
     </xs:appinfo>
   </xs:annotation>
    
diff --git a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section07/discriminators/discriminator2.tdml b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section07/discriminators/discriminator2.tdml
new file mode 100644
index 0000000..827c1ea
--- /dev/null
+++ b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section07/discriminators/discriminator2.tdml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016 Tresys Technology, LLC. All rights reserved.
+
+ Developed by: Tresys Technology, LLC
+ http://www.tresys.com
+
+ Permission is hereby granted, free of charge, to any person obtaining a 
+ copy of
+ this software and associated documentation files (the "Software"), to deal 
+ with
+ the Software without restriction, including without limitation the rights 
+ to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished 
+ to do
+ so, subject to the following conditions:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the names of Tresys Technology, nor the names of its contributors
+ may be used to endorse or promote products derived from this Software
+ without specific prior written permission.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+ OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
+ THE
+ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 
+ THE
+ SOFTWARE.
+-->
+<tdml:testSuite
+ suiteName="Discriminator2"
+ description="Section 7 - Discriminator"
+ xmlns:ex="http://example.com"
+ xmlns="http://example.com"
+ xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ defaultRoundTrip="true"
+>
+
+ <tdml:defineSchema name="s0">
+  <dfdl:format ref="ex:daffodilTest1" />
+
+  <xs:element name="e1">
+   <xs:complexType>
+    <xs:sequence>
+     <xs:annotation>
+      <xs:appinfo source="http://www.ogf.org/dfdl/">
+       <dfdl:discriminator
+        testKind="pattern"
+        testPattern="a.*" />
+      </xs:appinfo>
+     </xs:annotation>
+     <xs:sequence>
+      <xs:annotation>
+       <xs:appinfo source="http://www.ogf.org/dfdl/">
+        <dfdl:assert
+         testKind="expression"
+         test="{ fn:false() }" />
+       </xs:appinfo>
+      </xs:annotation>
+     </xs:sequence>
+     <xs:element
+      name="opt1"
+      minOccurs="0"
+      maxOccurs="1"
+      dfdl:occursCountKind="implicit"
+      type="xs:string"
+      dfdl:lengthKind="delimited"
+      dfdl:terminator=";"/>
+    </xs:sequence>
+   </xs:complexType>
+  </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase
+  name="discrimFailStopsFollowingAssert1"
+  model="s0"
+  root="e1"
+  description="verifies that a failing discriminator stops a following assert from evaluating. Pattern case."
+ >
+  <tdml:document>bbbbbb;</tdml:document>
+  <tdml:errors>
+   <tdml:error>failed</tdml:error>
+  </tdml:errors>
+ </tdml:parserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section12/lengthKind/implicit.tdml b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section12/lengthKind/implicit.tdml
index f8cef42..fe343a0 100644
--- a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section12/lengthKind/implicit.tdml
+++ b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section12/lengthKind/implicit.tdml
@@ -238,7 +238,10 @@
     <tdml:document><![CDATA[04:44:23.3000]]></tdml:document>

     <tdml:errors>

       <tdml:error>Schema Definition Error</tdml:error>

-      <tdml:error>Type time cannot have lengthKind='implicit' when representation='text'</tdml:error>

+      <tdml:error>time</tdml:error>
+      <tdml:error>lengthKind='implicit'</tdml:error>
+      <tdml:error></tdml:error>
+      <tdml:error>representation='text'</tdml:error>

     </tdml:errors>

   </tdml:parserTestCase>

 

diff --git a/daffodil-test/src/test/scala-new/edu/illinois/ncsa/daffodil/section07/discriminators/TestDiscriminators2.scala b/daffodil-test/src/test/scala-new/edu/illinois/ncsa/daffodil/section07/discriminators/TestDiscriminators2.scala
new file mode 100644
index 0000000..ab0f6b4
--- /dev/null
+++ b/daffodil-test/src/test/scala-new/edu/illinois/ncsa/daffodil/section07/discriminators/TestDiscriminators2.scala
@@ -0,0 +1,55 @@
+/* Copyright (c) 2012-2013 Tresys Technology, LLC. All rights reserved.
+ *
+ * Developed by: Tresys Technology, LLC
+ *               http://www.tresys.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal with
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimers.
+ *
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimers in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *  3. Neither the names of Tresys Technology, nor the names of its contributors
+ *     may be used to endorse or promote products derived from this Software
+ *     without specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+ * SOFTWARE.
+ */
+
+package edu.illinois.ncsa.daffodil.section07.discriminators
+
+import org.junit.Test
+import edu.illinois.ncsa.daffodil.tdml.Runner
+import org.junit.AfterClass
+
+object TestDiscriminators2 {
+  val testDir = "/edu/illinois/ncsa/daffodil/section07/discriminators/"
+  val runner2 = Runner(testDir, "discriminator2.tdml")
+
+  @AfterClass def shutDown() {
+    runner2.reset
+  }
+
+}
+
+class TestDiscriminators2 {
+
+  import TestDiscriminators2._
+
+  @Test def test_discrimFailStopsFollowingAssert1() { runner2.runOneTest("discrimFailStopsFollowingAssert1") }
+
+}