mbeckerle commented on a change in pull request #259: Incremental progress on 
schema compilation space/speed issue.
URL: https://github.com/apache/incubator-daffodil/pull/259#discussion_r301233918
 
 

 ##########
 File path: 
daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
 ##########
 @@ -1103,64 +1104,123 @@ case class NamedStep(s: String, predArg: 
Option[PredicateExpression])
     res
   }
 
-  lazy val dpathElementCompileInfo = stepElement
+  lazy val dpathElementCompileInfos = stepElements
 
   lazy val downwardStep = {
-    if (stepElement.isArray && pred.isDefined) {
-      Assert.invariant(pred.get.targetType == NodeInfo.ArrayIndex)
-      val indexRecipe = pred.get.compiledDPath
-      new DownArrayOccurrence(dpathElementCompileInfo, indexRecipe)
-    } else if (stepElement.isArray && targetType == NodeInfo.Exists) {
-      new DownArrayExists(dpathElementCompileInfo)
-    } else if (stepElement.isArray) {
-      schemaDefinitionUnless(targetType == NodeInfo.Array, "Query-style paths 
not supported. Must have '[...]' after array-element's name. Offending path 
step: '%s'.", step)
-      new DownArray(dpathElementCompileInfo)
+    if (isArray) {
+      if (pred.isDefined) {
+        Assert.invariant(pred.get.targetType == NodeInfo.ArrayIndex)
+        val indexRecipe = pred.get.compiledDPath
+        new DownArrayOccurrence(dpathElementCompileInfos.head, indexRecipe)
+      } else if (targetType == NodeInfo.Exists) {
+        new DownArrayExists(dpathElementCompileInfos.head)
+      } else {
+        schemaDefinitionUnless(targetType == NodeInfo.Array, "Query-style 
paths not supported. Must have '[...]' after array-element's name. Offending 
path step: '%s'.", step)
+        new DownArray(dpathElementCompileInfos.head)
+      }
     } else {
       //
       // Note: DFDL spec allows a[exp] if a is not an array, but it's a 
processing
       // error if exp doesn't evaluate to 1.
       // TODO: Implement this.
       if (pred.isDefined) subsetError("Indexing is only allowed on arrays. 
Offending path step: '%s%s'.", step, pred.get.text)
-      new DownElement(dpathElementCompileInfo)
+      new DownElement(dpathElementCompileInfos.head)
     }
   }
 
   override def text = step
 
-  private def die = {
-    Assert.invariantFailed("should have thrown")
-  }
   /*
-   * The ERD of the element that corresponds to this path step
-   * (or SDE trying to find it.)
+   * The ERDs of the elements that corresponds to this path step
+   * (or SDE trying to find them.)
+   *
+   * There are multiple step elements because an upward relative path can be 
say
+   * from an element inside a global group, upward to multiple group
+   * references where the relative path then steps downward to
+   * different elements having the same name.
+   *
+   * E.g., ../../b must type check for all possible b that this path
+   * can refer to. If that path appears inside a global group definition,
+   * then every place that group is used must have a corresponding b
+   * child element that satisfies this path, and which type-checks.
+   *
+   * So long as they all type check, the we can generate the
+   * downward step we need in a way that works universally for all
+   * uses of the path.
    */
-  override lazy val stepElement: DPathElementCompileInfo = {
-    val stepElem = if (isFirstStep) {
-      if (isAbsolutePath) {
-        // has to be the root element, but we have to make sure the name 
matches.
-        rootElement.findRoot(stepQName, this)
-        rootElement
+  override lazy val stepElements: Seq[DPathElementCompileInfo] = 
LV('stepElements) {
+    val res: Seq[DPathElementCompileInfo] =
+      if (isFirstStep) {
+        if (isAbsolutePath) {
+          // has to be the root element, but we have to make sure the name 
matches.
+          val re = rootElement
+          re.findRoot(stepQName, this)
+          Seq(re)
+        } else {
+          // Since we're first we start from the element, or nearest enclosing
+          // for this path expression.
+
+          // That can already be multiple such, because this expression could 
be
+          // say on the initiator property of an inner sequence inside a 
global sequence
+          // group def. That global def could be used inside the complex type 
of
+          // 3 different elements. So we would have 3 elementCompileInfos for 
this
+          // step.
+          //
+          // Also since we're the first step, and this is a named step, this 
has
+          // to be downward to a child. Assertion check here is just in case
+          // somebody refactors this code elsewhere, as it is a very strong
+          // assumption for this algorithm.
+          Assert.invariant(this.isInstanceOf[NamedStep])
+          //
+          // All enclosing elements for this path step must be able to
+          // find a named child that matches.
+          //
+          val nc = compileInfo.elementCompileInfos.map {
+            _.findNamedChild(stepQName, this) // will SDE on not found.
+          }
+          nc
+        }
       } else {
-        // since we're first we start from the element, or nearest enclosing
-        val nc = compileInfo.elementCompileInfo.getOrElse {
-          // happens for example if you have defaultValue="false" since false 
looks like a path step, but is really illegal. should be fn:false().
-          compileInfo.SDE("The expression path step '%s' has no defined 
enclosing element.", s)
-        }.findNamedChild(stepQName, this)
-        nc
+        // This is not first step so we are extension of prior step
+        //
+        //        // First we have to walk up any chain of relative upward 
path steps.
 
 Review comment:
   Delete commented code.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to