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

mbeckerle pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git


The following commit(s) were added to refs/heads/main by this push:
     new ae0f727  variableMap is now only accessible from PState/UState methods.
ae0f727 is described below

commit ae0f727e392e0b424aa8db0af395deae148044e0
Author: Michael Beckerle <[email protected]>
AuthorDate: Mon Sep 27 15:25:58 2021 -0400

    variableMap is now only accessible from PState/UState methods.
    
    Those methods provide initialization, get/set, and 
newInstance/removeInstance capabilities.
    
    There's no bypassing this, except for the interactivedebugger which has a 
special access method.
    
    This insures proper maintenance of the changedVariablesStack.
    
    DAFFODIL-2565
---
 .../unparsers/ExpressionEvaluatingUnparsers.scala  |  6 +--
 .../daffodil/debugger/InteractiveDebugger.scala    |  9 ++--
 .../scala/org/apache/daffodil/dpath/DPath.scala    |  4 --
 .../org/apache/daffodil/dpath/DPathRuntime.scala   | 13 ++----
 .../scala/org/apache/daffodil/dpath/DState.scala   | 47 ++-----------------
 .../apache/daffodil/processors/DataProcessor.scala |  6 +--
 .../daffodil/processors/ProcessorStateBases.scala  | 54 ++++++++++++++++------
 .../apache/daffodil/processors/VariableMap1.scala  | 15 +++---
 .../daffodil/processors/parsers/PState.scala       | 13 ++----
 .../daffodil/processors/unparsers/UState.scala     | 16 +++----
 10 files changed, 75 insertions(+), 108 deletions(-)

diff --git 
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
 
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
index 39eca0d..effd3c0 100644
--- 
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
+++ 
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
@@ -42,7 +42,7 @@ final class SetVariableSuspendableExpression(
   extends SuspendableExpression {
 
   override protected def processExpressionResult(ustate: UState, v: 
DataValuePrimitive): Unit = {
-      ustate.variableMap.setVariable(rd, v, referencingContext, ustate)
+      ustate.setVariable(rd, v, referencingContext)
   }
 
   override protected def maybeKnownLengthInBits(ustate: UState) = MaybeULong(0)
@@ -101,7 +101,7 @@ class NewVariableInstanceStartUnparser(override val 
context: VariableRuntimeData
   override lazy val childProcessors = Vector()
 
   override def unparse(state: UState) = {
-    val nvi = state.variableMap.newVariableInstance(context)
+    val nvi = state.newVariableInstance(context)
 
     if (context.maybeDefaultValueExpr.isDefined) {
       val dve = context.maybeDefaultValueExpr.get
@@ -123,7 +123,7 @@ class NewVariableInstanceEndUnparser(override val context: 
VariableRuntimeData)
 
   override lazy val childProcessors = Vector()
 
-  override def unparse(state: UState) = 
state.variableMap.removeVariableInstance(context)
+  override def unparse(state: UState) = state.removeVariableInstance(context)
 }
 
 class TypeValueCalcUnparser(typeCalculator: TypeCalculator, repTypeUnparser: 
Unparser, e: ElementRuntimeData, repTypeRuntimeData: ElementRuntimeData)
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
index 422823a..ea2025d 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
@@ -1669,7 +1669,7 @@ class InteractiveDebugger(runner: 
InteractiveDebuggerRunner, eCompilers: Express
         }
 
         def act(args: Seq[String], state: ParseOrUnparseState, processor: 
Processor): DebugState.Type = {
-          val vmap = state.variableMap
+          val vmap = state.variableMapForDebugger
           val allQNames = vmap.qnames
           val qnamesToPrint =
             if (args.size == 0) allQNames
@@ -1690,12 +1690,13 @@ class InteractiveDebugger(runner: 
InteractiveDebuggerRunner, eCompilers: Express
         }
 
         def diff(pre: StateForDebugger, post: StateForDebugger): Boolean = {
-          pre.variableMap.qnames.foldLeft(false) { case (foundDiff, qname) =>
-            val pre_instance = pre.variableMap.find(qname).get
+          val prevmap = pre.variableMapForDebugger
+          prevmap.qnames.foldLeft(false) { case (foundDiff, qname) =>
+            val pre_instance = prevmap.find(qname).get
             val pre_value = pre_instance.value
             val pre_state = pre_instance.state
 
-            val cur_instance = post.variableMap.find(qname).get
+            val cur_instance = post.variableMapForDebugger.find(qname).get
             val cur_value = cur_instance.value
             val cur_state = cur_instance.state
 
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
index a59dd4d..3e5acdf 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPath.scala
@@ -249,10 +249,6 @@ final class RuntimeExpressionDPath[T <: AnyRef](qn: 
NamedQName, tt: NodeInfo.Kin
 
   private def evaluateExpression(state: ParseOrUnparseState, dstate: DState): 
DState = {
     recipe.runExpression(state, dstate) // initializes dstate from state, then 
runs
-    state match {
-      case ustate: UState => // nothing. These are shared already
-      case pstate: PState => pstate.setVariableMap(dstate.vmap) // TODO: if 
we're always copying this back, then no point in trying to isolate. Just share 
just like in UState case.
-    }
     dstate
   }
 
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
index 1337696..f856b82 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DPathRuntime.scala
@@ -17,10 +17,8 @@
 
 package org.apache.daffodil.dpath
 
-import java.lang.{ Number => JNumber }
-
+import java.lang.{Number => JNumber}
 import scala.xml.NodeSeq.seqToNodeSeq
-
 import org.apache.daffodil.api.DaffodilTunables
 import org.apache.daffodil.dsom.DPathCompileInfo
 import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
@@ -38,6 +36,7 @@ import org.apache.daffodil.processors.CompileState
 import org.apache.daffodil.processors.ParseOrUnparseState
 import org.apache.daffodil.processors.ProcessingError
 import org.apache.daffodil.processors.VariableException
+import org.apache.daffodil.processors.VariableHasNoValue
 import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.util.Misc
 
@@ -63,10 +62,8 @@ class CompiledDPath(val ops: RecipeOp*) extends Serializable 
{
       dstate.setContextNode(state.thisElement.asInstanceOf[DINode]) // used 
for diagnostics
     }
 
-    dstate.setVMap(state.variableMap)
     dstate.setArrayPos(state.arrayPos)
     dstate.setErrorOrWarn(state)
-    dstate.setParseOrUnparseState(state)
     dstate.resetValue
     dstate.isCompile = state match {
       case cs: CompileState => true
@@ -184,9 +181,9 @@ case class VRef(vrd: VariableRuntimeData, context: 
ThrowsSDE)
   extends RecipeOp {
 
   override def run(dstate: DState): Unit = {
-    Assert.invariant(dstate.vmap != null)
-    Assert.invariant(dstate.parseOrUnparseState.isDefined)
-    dstate.setCurrentValue(dstate.vmap.readVariable(vrd, context, 
dstate.parseOrUnparseState.get))
+    if(dstate.parseOrUnparseState.isEmpty) throw new 
VariableHasNoValue(vrd.globalQName, vrd)
+    val value = dstate.parseOrUnparseState.get.getVariable(vrd, context)
+    dstate.setCurrentValue(value)
   }
 
   override def toXML = toXML("$" + vrd.globalQName.toPrettyString)
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
index 422baf7..0d160f2 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DState.scala
@@ -32,14 +32,11 @@ import 
org.apache.daffodil.infoset.InfosetNoNextSiblingException
 import org.apache.daffodil.infoset.RetryableException
 import org.apache.daffodil.processors.ParseOrUnparseState
 import org.apache.daffodil.processors.SchemaSetRuntimeData
-import org.apache.daffodil.processors.VariableBox
-import org.apache.daffodil.processors.VariableMap
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe.Nope
 import org.apache.daffodil.util.Maybe.One; object EqualityNoWarn2 { 
EqualitySuppressUnusedImportWarning() }
-import java.math.{ BigDecimal => JBigDecimal }
-import java.math.{ BigInteger => JBigInt }
-
+import java.math.{BigDecimal => JBigDecimal}
+import java.math.{BigInteger => JBigInt}
 import org.apache.daffodil.api.DaffodilTunables
 import org.apache.daffodil.api.DataLocation
 import org.apache.daffodil.api.WarnID
@@ -116,7 +113,8 @@ case object UnparserNonBlocking extends EvalMode
  */
 case class DState(
   val maybeSsrd: Maybe[SchemaSetRuntimeData],
-  tunable: DaffodilTunables) {
+  tunable: DaffodilTunables,
+  val parseOrUnparseState: Maybe[ParseOrUnparseState]) {
   import org.apache.daffodil.util.Numbers._
 
   var isCompile = false
@@ -313,35 +311,6 @@ case class DState(
     }
   }
 
-  private var _vbox: VariableBox = null
-
-  def vmap = {
-    Assert.usage(_vbox ne null)
-    _vbox.vmap
-  }
-
-  /**
-   * Used by PState and parser, where we want to isolate the modifications
-   * to the vmap per expression evaluation. This isolate makes backtracking
-   * changes to the vmap easy. Just don't copy the vmap back from the DState
-   * into the PState, and the changes are gone.
-   */
-  def setVMap(m: VariableMap): Unit = {
-    if (_vbox eq null) {
-      _vbox = new VariableBox(m)
-    } else {
-      _vbox.setVMap(m)
-    }
-  }
-
-  /**
-   * Used by UState, where we want to shared the vmap as modified by the
-   * expression evaluations that use the DState.
-   */
-  def setVBox(box: VariableBox): Unit = {
-    _vbox = box
-  }
-
   def runtimeData = {
     if (contextNode.isDefined) One(contextNode.get.erd)
     else Nope
@@ -391,11 +360,6 @@ case class DState(
     _arrayPos = arrayPos1b
   }
 
-  private var _parseOrUnparseState: Maybe[ParseOrUnparseState] = Nope
-  def parseOrUnparseState = _parseOrUnparseState
-  def setParseOrUnparseState(state: ParseOrUnparseState): Unit = {
-    _parseOrUnparseState = One(state)
-  }
 
   def SDE(formatString: String, args: Any*) = {
     if (isCompile) {
@@ -462,7 +426,7 @@ object DState {
 
 class DStateForConstantFolding(
   override val compileInfo: DPathCompileInfo,
-  tunable: DaffodilTunables) extends DState(Nope, tunable) {
+  tunable: DaffodilTunables) extends DState(Nope, tunable, Nope) {
   private def die = throw new java.lang.IllegalStateException("No infoset at 
compile time.")
 
   override def currentSimple = currentNode.asInstanceOf[DISimple]
@@ -471,7 +435,6 @@ class DStateForConstantFolding(
   override def currentComplex = die
   override def currentNode = new FakeDINode
   override def runtimeData = die
-  override def vmap = die
   override def selfMove() = die
   override def fnExists() = die
   override def arrayPos = die
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
index c87c9c0..98d4a3f 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
@@ -496,8 +496,7 @@ class DataProcessor private (
 
         // Force the evaluation of any defineVariable's with non-constant 
default
         // value expressions
-        state.variableMap.forceExpressionEvaluations(state)
-        state.variableMap.setFirstInstanceInitialValues()
+        state.initializeVariables()
 
         this.startElement(state, p)
         p.parse1(state)
@@ -650,8 +649,7 @@ class DataProcessor private (
 
     // Force the evaluation of any defineVariable's with non-constant default
     // value expressions
-    state.variableMap.forceExpressionEvaluations(state)
-    state.variableMap.setFirstInstanceInitialValues()
+    state.initializeVariables()
 
     rootUnparser.unparse1(state)
     state.popTRD(rootUnparser.context.asInstanceOf[TermRuntimeData])
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
index 13efce8..9e5cd3b 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
@@ -19,10 +19,8 @@ package org.apache.daffodil.processors
 
 import java.nio.CharBuffer
 import java.nio.LongBuffer
-
 import org.apache.daffodil.api.DFDL
 import org.apache.daffodil.api.DaffodilTunables
-import org.apache.daffodil.api.DataLocation
 import org.apache.daffodil.api.Diagnostic
 import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.dpath.DState
@@ -30,12 +28,9 @@ import org.apache.daffodil.dsom.RuntimeSchemaDefinitionError
 import org.apache.daffodil.dsom.RuntimeSchemaDefinitionWarning
 import org.apache.daffodil.dsom.ValidationError
 import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.exceptions.SavesErrorsAndWarnings
-import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.io.DataStreamCommon
 import org.apache.daffodil.io.LocalBufferMixin
 import org.apache.daffodil.util.MStackOfLong
-import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe.Nope
 import org.apache.daffodil.util.Maybe.One
 import org.apache.daffodil.util.MaybeULong
@@ -60,9 +55,8 @@ import 
org.apache.daffodil.processors.charset.BitsCharsetEncoder
 import org.apache.daffodil.processors.unparsers.UState
 import org.apache.daffodil.processors.dfa.Registers
 import org.apache.daffodil.processors.dfa.RegistersPool
-import org.apache.daffodil.processors.dfa.RegistersPool
-import org.apache.daffodil.processors.dfa.RegistersPool
 import org.apache.daffodil.dsom.DPathCompileInfo
+import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
 
 /**
  * Trait mixed into the PState.Mark object class and the ParseOrUnparseState
@@ -76,7 +70,7 @@ trait StateForDebugger {
   def childPos: Long
   def groupPos: Long
   def arrayPos: Long
-  def variableMap: VariableMap
+  def variableMapForDebugger: VariableMap
   def delimitedParseResult: Maybe[dfa.ParseResult]
   def withinHiddenNest: Boolean
   def suspensions: Seq[Suspension]
@@ -89,7 +83,7 @@ case class TupleForDebugger(
   val childPos: Long,
   val groupPos: Long,
   val arrayPos: Long,
-  val variableMap: VariableMap,
+  val variableMapForDebugger: VariableMap,
   val delimitedParseResult: Maybe[dfa.ParseResult],
   val withinHiddenNest: Boolean,
   val suspensions: Seq[Suspension])
@@ -354,13 +348,38 @@ abstract class ParseOrUnparseState protected (
   }
 
   /**
-   * Variable map provides access to variable bindings.
+   * The variable map is accessed via methods below to set/get and 
create/remove instances.
+   *
+   * Everything should access the variables via these methods, not by using 
the variableMap object
+   * directly.
+   *
+   * The exception to this is the interactive debugger.
    */
-  final def variableMap = variableBox.vmap
-  final def setVariableMap(newMap: VariableMap): Unit = {
+  final protected def variableMap = variableBox.vmap
+  final protected def setVariableMap(newMap: VariableMap): Unit = {
     variableBox.setVMap(newMap)
   }
 
+  final def initializeVariables(): Unit = {
+    variableMap.forceExpressionEvaluations(this)
+    variableMap.setFirstInstanceInitialValues()
+  }
+
+  def setVariable(vrd: VariableRuntimeData, newValue: DataValuePrimitive, 
referringContext: ThrowsSDE): Unit
+
+  def getVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE): 
DataValuePrimitive
+
+  def newVariableInstance(vrd: VariableRuntimeData): VariableInstance
+
+  def removeVariableInstance(vrd: VariableRuntimeData): Unit
+
+  /**
+   * The interactive debugger can access the variableMap object state directly.
+   *
+   * Everthing else should get/set variables using methods on the 
PState/UState objects.
+   */
+  final def variableMapForDebugger = variableMap
+
   final protected var _processorStatus: ProcessorResult = Success
   final protected var _validationStatus: Boolean = true
 
@@ -417,7 +436,7 @@ abstract class ParseOrUnparseState protected (
 
   private val maybeSsrd = if (dataProc.isDefined) { One(dataProc.get.ssrd) } 
else Maybe.Nope
 
-  private val _dState = new DState(maybeSsrd, tunable)
+  private val _dState = new DState(maybeSsrd, tunable, One(this))
 
   /**
    * Used when evaluating expressions. Holds state of expression
@@ -547,7 +566,6 @@ abstract class ParseOrUnparseState protected (
 
     def finalCheck() = pool.finalCheck
   }
-
 }
 
 /**
@@ -600,4 +618,12 @@ final class CompileState(tci: DPathCompileInfo, 
maybeDataProc: Maybe[DataProcess
 
   def regexMatchBuffer: CharBuffer = Assert.usageError("Not to be used.")
   def regexMatchBitPositionBuffer: LongBuffer = Assert.usageError("Not to be 
used.")
+
+
+  // $COVERAGE-OFF$
+  override def setVariable(vrd: VariableRuntimeData, newValue: 
DataValuePrimitive, referringContext: ThrowsSDE): Unit = Assert.usageError("Not 
to be used.")
+  override def getVariable(vrd: VariableRuntimeData, referringContext: 
ThrowsSDE) = Assert.usageError("Not to be used.")
+  override def newVariableInstance(vrd: VariableRuntimeData) = 
Assert.usageError("Not to be used.")
+  override def removeVariableInstance(vrd: VariableRuntimeData): Unit = 
Assert.usageError("Not to be used.")
+  // $COVERAGE-ON$
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
index c4cdd9b..80f470d 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala
@@ -340,13 +340,13 @@ class VariableMap private(vTable: Map[GlobalQName, 
ArrayBuffer[VariableInstance]
    * Returns the value of a variable and sets the state of the variable to be
    * VariableRead.
    */
-  def readVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE, 
pstate: ParseOrUnparseState): DataValuePrimitive = {
+  def readVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE, 
state: ParseOrUnparseState): DataValuePrimitive = {
     val varQName = vrd.globalQName
     vrd.direction match {
-      case VariableDirection.ParseOnly if (!pstate.isInstanceOf[PState]) =>
-        pstate.SDE("Attempting to read variable %s which is marked as 
parseOnly during unparsing".format(varQName))
-      case VariableDirection.UnparseOnly if (!pstate.isInstanceOf[UState]) =>
-        pstate.SDE("Attempting to read variable %s which is marked as 
unparseOnly during parsing".format(varQName))
+      case VariableDirection.ParseOnly if (!state.isInstanceOf[PState]) =>
+        state.SDE("Attempting to read variable %s which is marked as parseOnly 
during unparsing".format(varQName))
+      case VariableDirection.UnparseOnly if (!state.isInstanceOf[UState]) =>
+        state.SDE("Attempting to read variable %s which is marked as 
unparseOnly during parsing".format(varQName))
       case _ => // Do nothing
     }
 
@@ -356,9 +356,6 @@ class VariableMap private(vTable: Map[GlobalQName, 
ArrayBuffer[VariableInstance]
       variable.state match {
         case VariableRead if (variable.value.isDefined) => 
variable.value.getNonNullable
         case VariableDefined | VariableSet if (variable.value.isDefined) => {
-          if (pstate.isInstanceOf[PState])
-            pstate.asInstanceOf[PState].markVariableRead(vrd)
-
           variable.setState(VariableRead)
           variable.value.getNonNullable
         }
@@ -369,7 +366,7 @@ class VariableMap private(vTable: Map[GlobalQName, 
ArrayBuffer[VariableInstance]
         // have a defined value
         case VariableUndefined if 
(variable.rd.maybeDefaultValueExpr.isDefined) => {
           variable.setState(VariableBeingDefined)
-          val res = 
DataValue.unsafeFromAnyRef(variable.rd.maybeDefaultValueExpr.get.evaluate(pstate))
+          val res = 
DataValue.unsafeFromAnyRef(variable.rd.maybeDefaultValueExpr.get.evaluate(state))
 
           // Need to update the variable's value with the result of the
           // expression
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
index b3a6437..f525034 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
@@ -328,22 +328,15 @@ final class PState private (
     this.infoset = newParent
   }
 
-  def setVariable(vrd: VariableRuntimeData, newValue: DataValuePrimitive, 
referringContext: ThrowsSDE): Unit = {
+  override def setVariable(vrd: VariableRuntimeData, newValue: 
DataValuePrimitive, referringContext: ThrowsSDE): Unit = {
     variableMap.setVariable(vrd, newValue, referringContext, this)
     changedVariablesStack.top += vrd.globalQName
   }
 
-  def getVariable(vrd: VariableRuntimeData, referringContext: ThrowsSDE): 
DataValuePrimitive = {
+  override def getVariable(vrd: VariableRuntimeData, referringContext: 
ThrowsSDE): DataValuePrimitive = {
     val res = variableMap.readVariable(vrd, referringContext, this)
-    res
-  }
-
-  /**
-   * Note that this function does not actually read the variable, it is used
-   * just to track that the variable was read in case we need to backtrack.
-   */
-  def markVariableRead(vrd: VariableRuntimeData): Unit = {
     changedVariablesStack.top += vrd.globalQName
+    res
   }
 
   def newVariableInstance(vrd: VariableRuntimeData): VariableInstance = {
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
index 01c789a..31cc559 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
@@ -50,6 +50,7 @@ import org.apache.daffodil.processors.SuspensionTracker
 import org.apache.daffodil.processors.TermRuntimeData
 import org.apache.daffodil.processors.UnparseResult
 import org.apache.daffodil.processors.VariableBox
+import org.apache.daffodil.processors.VariableInstance
 import org.apache.daffodil.processors.VariableMap
 import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.processors.charset.BitsCharset
@@ -76,7 +77,8 @@ abstract class UState(
   extends ParseOrUnparseState(vbox, diagnosticsArg, dataProcArg, tunable)
   with Cursor[InfosetAccessor] with ThrowsSDE with SavesErrorsAndWarnings {
 
-  final def setVariable(vrd: VariableRuntimeData, newValue: 
DataValuePrimitive, referringContext: ThrowsSDE) =
+
+  final override def setVariable(vrd: VariableRuntimeData, newValue: 
DataValuePrimitive, referringContext: ThrowsSDE) =
     vbox.vmap.setVariable(vrd, newValue, referringContext, this)
 
   /**
@@ -86,10 +88,12 @@ abstract class UState(
    * @param referringContext Where to place blame if there is an error.
    * @return The data value of the variable, or throws exceptions if there is 
no value.
    */
-  final def getVariable(vrd: VariableRuntimeData, referringContext: 
ThrowsSDE): DataValuePrimitive =
+  final override def getVariable(vrd: VariableRuntimeData, referringContext: 
ThrowsSDE): DataValuePrimitive =
     vbox.vmap.readVariable(vrd, referringContext, this)
 
+  final override def newVariableInstance(vrd: VariableRuntimeData): 
VariableInstance = variableMap.newVariableInstance(vrd)
 
+  final override def removeVariableInstance(vrd: VariableRuntimeData): Unit = 
variableMap.removeVariableInstance(vrd)
 
   /**
    * Push onto the dynamic TRD context stack
@@ -119,7 +123,6 @@ abstract class UState(
   def currentInfosetNode: DINode
   def currentInfosetNodeMaybe: Maybe[DINode]
   def escapeSchemeEVCache: MStackOfMaybe[EscapeSchemeUnparserHelper]
-  def setVariables(newVariableMap: VariableMap): Unit
 
   // def charBufferDataOutputStream: LocalStack[CharBufferDataOutputStream]
   def withUnparserDataInputStream: LocalStack[StringDataInputStreamForUnparse]
@@ -381,7 +384,6 @@ final class UStateForSuspension(
   dState.setMode(UnparserBlocking)
   dState.setCurrentNode(thisElement.asInstanceOf[DINode])
   dState.setContextNode(thisElement.asInstanceOf[DINode])
-  dState.setVBox(vbox)
   dState.setErrorOrWarn(this)
 
   private def die = Assert.invariantFailed("Function should never be needed in 
UStateForSuspension")
@@ -432,8 +434,6 @@ final class UStateForSuspension(
 
   override def escapeSchemeEVCache: MStackOfMaybe[EscapeSchemeUnparserHelper] 
= escapeSchemeEVCacheMaybe.get
 
-  override def setVariables(newVariableMap: VariableMap) = die
-
   override def pushTRD(trd: TermRuntimeData): Unit = die
   override def maybeTopTRD() = die
   override def popTRD(trd: TermRuntimeData): TermRuntimeData = die
@@ -612,10 +612,6 @@ final class UStateMain private (
     }.toList
   }
 
-  override def setVariables(newVariableMap: VariableMap) = {
-    setVariableMap(newVariableMap)
-  }
-
   /**
    * For outputValueCalc we accumulate the suspendables here.
    *

Reply via email to