The default value expression should be evaluated not on demand, but when the 
sequence is entered. That will give it the correct context.

The evaluation of the default value expression should work the same way as if 
it was in a setVariable annotation, with the exception that it sets the default 
value, not the assigned value.

________________________________
From: Adams, Joshua <jad...@owlcyberdefense.com>
Sent: Thursday, October 29, 2020 4:07:39 PM
To: dev@daffodil.apache.org <dev@daffodil.apache.org>
Subject: Problems with expressions and variables

After spending a while banging my head against a wall as to why my simple test 
demonstrating newVariableInstance with a default value expression wasn't 
working, I think I understand what is going wrong now.

Here is a copy of the simple test case for newVariableInstance with a default 
value expression:

    <xs:element name="nvi12">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="newDefaultValue" type="xsd:int" 
dfdl:lengthKind="explicit" dfdl:length="1" />
          <xs:element name="innerSeq">
            <xs:complexType>
              <xs:sequence>
                <xs:annotation>
                  <xs:appinfo source="http://www.ogf.org/dfdl/";>
                    <dfdl:newVariableInstance ref="ex:myVar1"
                      defaultValue="{ ../ex:newDefaultValue }" />
                  </xs:appinfo>
                </xs:annotation>
                <xs:element name="varValue" type="xs:int"
                  dfdl:inputValueCalc="{ $ex:myVar1 }" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>

I had added code to the VariableMap1 readVariable function to evaluate the 
expression if the variable didn't already have a value, so it was getting 
evaluated when element 'varValue' was being parsed.  This expression evaluation 
then triggered the evaluation of the myVar1, which itself is an expression that 
then needs to be evaluated.  The problem is when Daffodil attempts to run the 
expression for the newVariableInstance defaultValue, it does so from the 
context of 'varValue' and ultimately fails.

To me this seems like a problem that could potentially affect any expression 
that then references another non-constant expression.  I took a quick look 
through our tests and I was unable to find a test case that covered this 
scenario.  Is this something that Daffodil should support?  I took a look 
through the spec and didn't find anything prohibiting this, and it seems like 
my test case would describe the typical use case for newVariableInstance 
referencing a non-constant expression.

Assuming this test is a valid use case for a default value as an expression, 
the issue becomes when should the expression be evaluated?  This also could 
have issues that require some changes to the variable API.  My initial approach 
I described earlier attempted to evaluate the expression when the variable was 
read, but that resulted in an incorrect context for evaluating the variable's 
expression.  Another option would be to evaluate the expression when the 
VariableRuntimeData structure is created for the myVar1's newVariableInstance.  
This is the location where values are set for constant expressions, but the 
VariableRuntimeData class doesn't seem to have access to the PState or UState 
needed to evaluate non-constant expressions.

Just want to make sure that this is a valid test case and if so, what approach 
should be taken to get this working.

Josh

Reply via email to